Search code examples
c++boost-spiritboost-spirit-qi

Using a pointer to a parser in boost::spirit


Basically I'm doing an expression parser. As I'm in need of as good as possible performance, and according to the documentation construction of a grammar can be rather slow, I'd like to reuse the grammar and bind the symbol table just before parsing. As the client of the grammar is likely to have a symbol table that's constructed and maintained ahead of parsing, I'd ideally like to avoid copying of the actual table as well which leads me to the following code ( simplified ) for translating terms:

qi::symbols< char, double >* m_Symbols;
qi::rule< Iterator, double(), ascii::space_type > m_Val;

m_Val = qi::int_[ _val = boost::phoenix::static_cast_< double >( boost::spirit::_1 ) ] | qi::double_ | m_Symbols;

The problem here is m_Symbols. What I'd like is to m_Val to hold m_Symbols by reference, as when we're binding the symbol table I'm naturally modifying the pointer, which I presume can somehow be solved by the use of boost::phoenix::ref? But the larger problem is that I can't seem to use pointer to parsers when compositing new parser. Using dereference in the expression dereferences m_Symbols straight away, which is unwanted, I want to delay the dereferencing to parse time.


Solution

  • I believe a simple

    qi::symbols<char, double>* m_Symbols;
    qi::rule<Iterator, double(), ascii::space_type> m_Val;
    
    m_Val = qi::int_ | qi::double_ | qi::lazy(*m_Symbols);
    

    should do what you need. The lazy parser (see here) evaluates its argument (repeatedly) at parse time only.