0x9093717
0x9093717

Reputation: 11

Boost::Spirit placeholders and alternative parser

// 1    
Mexpression = Mterm >> *(
    '+' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '+', _2)]
  | '-' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '-', _2)]
  );

Mterm = Mfactor >> *(   
    '*' >> Mfactor [qi::_val = phoenix::new_<BinaryNode>(_1, '*', _2)]
  | '/' >> Mfactor [qi::_val = phoenix::new_<BinaryNode>(_1, '/', _2)]
  );

Mfactor = Unpack 
    | '+' >> Mfactor [qi::_val = phoenix::new_<UnaryNode>('+', _1)] 
    | '-' >> Mfactor [qi::_val = phoenix::new_<UnaryNode>('-', _1)]
    | '(' >> Mexpression >> ')';`

`Error  2   error C2664: 'BinaryNode::BinaryNode(const BinaryNode &)' : cannot convert argument 3 from 'boost::mpl::void_' to 'anExpression *'  c:\boost_1_55_0\boost\spirit\home\phoenix\object\detail\new_eval.hpp    41  1   ConsoleApplication1
Error   1   error C2338: index_is_out_of_bounds c:\boost_1_55_0\boost\spirit\home\support\argument.hpp  103 1   ConsoleApplication1 `

And

c:\boost_1_55_0\boost\spirit\home\support\argument.hpp(166) : see reference to class template instantiation 'boost::spirit::result_of::get_arg<boost::fusion::vector1<Attribute &>,1>' being compiled with
[
Attribute=anExpression *
]

I'm coding a translator for a model language (there are several ebnf with main compositions given as a task.) and stuck somewhere at arithmetical operations.

(see 1 in paste)

here's a model to parse math' exprs,

unpack is somenode, something that can be executed, converted to anExpression *, and given as arg to BinaryNode

there are following rules.

    qi::rule<Iterator, anExpression *()> Unpack;
    qi::rule<Iterator, anExpression *()> Mexpression, Mterm, Mfactor; 

anExpression is an abstract class (Binary and Unary are public anExpression)

while compiling the whole program I have following errors:

fig2

I think that error 2 is the most important thing to fix first.

something like this in build log fig3


okay, I think that the mistake is in my way of semantic actions. I think there's not Mterm (or Mfactor) in _2 placeholder. there's something I'm doing wrong with this way of using semantics actions and alternative parser ( '|' )

I'll be glad to hear any ideas from you guys =)

Upvotes: 1

Views: 356

Answers (1)

sehe
sehe

Reputation: 393114

Mexpression = Mterm >> *(
    '+' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '+', _2)]
  | '-' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '-', _2)]
  );

Can't work indeed. You'd need to temporarily store the result attribute of the lhs Mterm. Luckily you should be able to use the result of the rule itself to do this:

Mexpression = Mterm [qi::_val = qi::_1] >> *(
    '+' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(qi::_val, '+', qi::_1)]
  | '-' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(qi::_val, '-', qi::_1)]
  );

However you may have to accomodate this in the constructor for your BinaryNode type.

This said:

  • I tend avoid semantic actions. As long as you're imperatively spelling each and every step out in the semantic action, what is the real benefit of using a parser generator like Spirit? It's no longer for Rapid Application Development
  • especially semantic actions doing dynamic allocations; it's very eay to create leaks in the presence of parser backtracking

That said, this kind of expression combination is about the only point where I think semantic actions can still be considered idiomatic in Spirit. The dynamic allocations most certainly are not.

Upvotes: 1

Related Questions