Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6791545
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T17:51:34+00:00 2026-05-26T17:51:34+00:00

I want to parse a file into an AST using Boost Spirit. The root

  • 0

I want to parse a file into an AST using Boost Spirit.

The root of my AST is a class with only one attribute :

typedef boost::variant<FunctionDeclaration, GlobalVariableDeclaration> FirstLevelBlock;

struct Program {
    std::vector<FirstLevelBlock> blocks;
};

BOOST_FUSION_ADAPT_STRUCT(
    ::Program,
    (std::vector<eddic::FirstLevelBlock>, blocks)
)

If I parse using a single rule :

program %= *(function | globalDeclaration);

it doesn’t compiles, but if I add a single string name to Program, it works well. I could use the vector as the root, but I want to use the class, because I want to add some methods to the Program class.

EDIT :

If I surround my program with braces, it works well :

program %= lexer.left_brace >> *(function | globalDeclaration) >> lexer.right_brace;

compiles and works fine, but :

program %= *(function | globalDeclaration);

does not compile…

Is there something in Boost Spirit that prevent using such simple rules ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T17:51:34+00:00Added an answer on May 26, 2026 at 5:51 pm

    Edited question version 2

    If I surround my program with braces, it works well […], but program %= *(function | globalDeclaration); does not compile…

    Is there something in Boost Spirit that prevent using such simple rules ?

    Firstly, we can’t really tell without the defintion for function and globalDeclaration.

    Secondly I tried, changing my PoC lines to

    static const qi::rule<It, Program(), space_type> program  = *(function | global);
    Program d = test("void test(); int abc; int xyz; void last();" , program); 
    

    Lo and behold, I get your compiler error! Now I would certainly agree that this looks very much like an attribute conversion bug. Also, Here is a preliminary workaround:

    program %= eps >> *(function | global);
    

    As you can see, qi::eps to the rescue


    Answer to original question version 1

    Mmm. I think you need to post a minimal working sample. Here is a proof of concept starting from your question, and it all works rather nicely.

    Note that I compiled with g++ -std=c++0x in order to get the default Attr parameter argument on the test function.

    #include <boost/spirit/include/qi.hpp>
    #include <boost/spirit/include/karma.hpp>
    #include <boost/fusion/adapted.hpp>
    #include <boost/strong_typedef.hpp>
    
    // added missing bits
    namespace eddic 
    {
        typedef std::string FunctionDeclaration;
        typedef std::string GlobalVariableDeclaration;
    
        typedef boost::variant<FunctionDeclaration, GlobalVariableDeclaration> FirstLevelBlock;
    }
    
    using namespace eddic;
    // end missing bits
    
    struct Program {
        std::vector<FirstLevelBlock> blocks;
    };
    
    BOOST_FUSION_ADAPT_STRUCT(
        ::Program,
        (std::vector<eddic::FirstLevelBlock>, blocks)
    )
    
    namespace /*anon*/
    {    
        using namespace boost::spirit::karma;
    
        struct dumpvariant : boost::static_visitor<std::ostream&>
        {
            dumpvariant(std::ostream& os) : _os(os) {}
            template <typename T> std::ostream& operator ()(const T& t) const
                { return _os << format(stream, t); }
    
          private: std::ostream& _os;
        };
    
        std::ostream& operator<<(std::ostream& os, const FirstLevelBlock& block)
        { 
            os << "variant[" << block.which() << ", ";
            boost::apply_visitor(dumpvariant(os), block);
            return os << "]";
        }
    
        std::ostream& operator<<(std::ostream& os, const std::vector<FirstLevelBlock>& blocks)
        { return os << format(-(stream % eol), blocks); }
    
        std::ostream& operator<<(std::ostream& os, const Program& program)
        { return os << "BEGIN\n" << program.blocks << "\nEND"; }
    }
    
    namespace qi = boost::spirit::qi;
    
    template <typename Rule, typename Attr = typename Rule::attr_type>
        Attr test(const std::string& input, const Rule& rule)
    {
        typedef std::string::const_iterator It;
        It f(input.begin()), l(input.end());
    
        Attr result;
        try
        {
            bool ok = qi::phrase_parse(f, l, rule, qi::space, result);
            if (!ok)
                std::cerr << " -- ERR: parse failed" << std::endl;
        } catch(qi::expectation_failure<It>& e)
        {
            std::cerr << " -- ERR: expectation failure at '" << std::string(e.first, e.last) << "'" << std::endl;
        }
        if (f!=l)
            std::cerr << " -- WARN: remaing input '" << std::string(f,l) << "'" << std::endl;
        return result;
    }
    
    int main()
    {
        typedef std::string::const_iterator It;
        static const qi::rule<It, FunctionDeclaration(), space_type>        function = "void " > +~qi::char_("()") > "();";
        static const qi::rule<It, GlobalVariableDeclaration(), space_type>  global   = "int "  > +~qi::char_(";")  > ";";
        static const qi::rule<It, FirstLevelBlock(), space_type>            block    = function | global;
        static const qi::rule<It, Program(), space_type>                    program  = '{' >> *(function | global) >> '}';
    
        FunctionDeclaration       a = test("void test();", function); 
        std::cout << "FunctionDeclaration a         : " << a << std::endl;
    
        GlobalVariableDeclaration b = test("int abc;", global); 
        std::cout << "GlobalVariableDeclaration b   : " << b << std::endl;
    
        FirstLevelBlock c = test("void more();", block); 
        std::cout << "FirstLevelBlock c             : " << c << std::endl;
    
        /*FirstLevelBlock*/ c = test("int bcd;", block); 
        std::cout << "FirstLevelBlock c             : " << c << std::endl;
    
        Program d = test("{"
                "void test();"
                "int abc"
                ";"
                "int xyz; void last();"
                "}", program); 
        std::cout << "Program d                     : " << d << std::endl;
    }
    

    Output:

    FunctionDeclaration a         : test
    GlobalVariableDeclaration b   : abc
    FirstLevelBlock c             : variant[1, more]
    FirstLevelBlock c             : variant[1, bcd]
    Program d                     : BEGIN
    test
    abc
    xyz
    last
    END
    

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I want to parse a PHP source file, into an AST (preferably as a
I want to be able to parse file paths like this one: /var/www/index.(htm|html|php|shtml) into
Scenario I want to parse a large CSV file and inserts data into the
I want to parse a large text file so that it breaks into a
I have an XML file which I want to convert into JSON file using
I have an XML file that I want to parse into a database in
I'm using Boost Spirit to parse source files in a little compiler project. If
I want to parse an excel file using the Apache POI library to boot
I want to parse a config file sorta thing, like so: [KEY:Value] [SUBKEY:SubValue] Now
I want to parse the html file, pdf file, csv file and text file.Now

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.