【问题标题】:Boost::Spirit placeholders and alternative parserBoost::Spirit 占位符和替代解析器
【发布时间】:2014-12-15 19:15:58
【问题描述】:
// 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 `

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 *
]

我正在编写一个模型语言的翻译器(有几个 ebnf 的主要成分作为任务给出。)并且在算术运算的某个地方卡住了。

(见粘贴中的 1)

这是一个解析数学表达式的模型,

unpack 是 somenode,可以执行,转换为表达式 *,并作为 arg 给 BinaryNode

有以下规则。

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

anExpression 是一个抽象类(Binary 和 Unary 都是 public anExpression)

编译整个程序时出现以下错误:

图2

我认为错误 2 是首先要修复的最重要的事情。

构建日志中的类似内容 图3


好的,我认为错误在于我的语义操作方式。我认为 _2 占位符中没有 Mterm(或 Mfactor)。使用语义操作和替代解析器('|')的这种方式我做错了什么

我很高兴听到你们的任何想法 =)

【问题讨论】:

  • 很抱歉将代码保存在 pastebin 中。

标签: c++ boost boost-spirit boost-spirit-qi boost-phoenix


【解决方案1】:
Mexpression = Mterm >> *(
    '+' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '+', _2)]
  | '-' >> Mterm [qi::_val = phoenix::new_<BinaryNode>(_1, '-', _2)]
  );

确实不行。您需要临时存储 lhs Mterm 的结果属性。幸运的是,您应该能够使用规则本身的结果来执行此操作:

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)]
  );

但是,您可能必须在 BinaryNode 类型的构造函数中容纳它。

这是说:

  • 我倾向于避免语义动作。只要你在语义动作中强制拼写每一步,使用像 Spirit 这样的解析器生成器的真正好处是什么?它不再适用于快速应用程序开发
  • 尤其是进行动态分配的语义动作;在存在解析器回溯的情况下很容易造成泄漏

也就是说,这种表达组合​​是我认为语义动作在 Spirit 中仍然可以被视为惯用的唯一一点。动态分配肯定不是。

【讨论】:

  • 这很有帮助。
  • 我说对了吗?我正在等待以下类型的结构 - binary(mterm, sign, binary (mterm, sign, binary(... ))) 这个解析器适合吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-15
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 2015-01-25
相关资源
最近更新 更多