【问题标题】:Generate expression using C++ boost::spirit PEG grammar使用 C++ boost::spirit PEG 语法生成表达式
【发布时间】:2011-03-13 23:30:07
【问题描述】:

我对 C++ 和 boost::spirit 非常陌生。尝试通过构建一个只有 || 的简单表达式树来学习两者。和 && 使用 PEG。我已经从文档中的 mini-xml 教程构建了许多代码部分。

这是code,它适用于简单的字符串,如“1 || 0”、“1 && 0”、“1 || 1 && 0”……但对于“(1 || 1) ”。我不太明白为什么它无法打印,即使它说解析成功。

另外,请进一步指导我如何使这段代码更直观、更易于维护。

【问题讨论】:

    标签: c++ expression-trees boost-spirit abstract-syntax-tree


    【解决方案1】:

    启用 Spirit 调试支持将有所帮助:

    a) 添加定义

    #define BOOST_SPIRIT_QI_DEBUG
    

    和 b) 在语法的构造函数中添加 a

    BOOST_SPIRIT_DEBUG_NODE(r);
    

    适用于所有规则(此处为 r)。结果,解析器将在运行时打印一个执行树,向您显示使用什么输入执行了哪些规则以及已填充了哪些属性值(有关详细信息,请参阅here)。

    作为一般说明(这可能不适用于您,因为您似乎正在尝试构建 AST),Spirit 的解析器已完全归因。这意味着您通常不需要任何语义操作来处理属性(请参阅hereherehere 以获得简要介绍)。

    【讨论】:

    • 谢谢@hkaiser!调试节点真的很有帮助,我能够解决我的错误(更新了要点)。问题在于我对指针的理解有限,语法运行良好(调试模式证实了这一点)。
    • 我如何将我的语义动作组合成一个 boost::phoenix 函数?目前我正在这样做: [at_c(_val) = new_()][*(at_c(_val)) = _1] [at_c(_val) = true] .这是有效的,但如果我尝试 [1,2,3] 它只考虑 3(忽略 1 和 2)。
    • @na_ka_na:如果仅执行逗号分隔表达式序列的最后一个元素,那么您将缺少定义逗号运算符重载的正确 Phoenix 头文件。它是#include ,IIRC。
    【解决方案2】:

    我不知道为什么您的特定 Spirit 代码不起作用,但鉴于您“对 C++ 非常陌生”并询问如何使您的代码从长远来看更易于维护,我的回答是:

    不要使用 Boost Spirit。使用易于理解的解析器生成器,例如 ANTLR(v2 可以生成 C++ 代码;v3 不能,所以使用 v2),或者 lex & yacc 或类似的。

    Boost Spirit 是一个很好的工具,可以用来展示 C++ 的某些特性能走多远。如果您的目标是直观且可维护的代码,则它对您没有特别的帮助,尤其是如果您还不是 C++ 专家(这对您没有任何影响)。

    【讨论】:

    • 我正在寻找深入研究 C++ 的方法,所以我认为 boost 库可能是一个很好的起点,(错误地?)假设它被广泛传播。我也会尝试 ANTLR。我的新工作场所迫使我将 C++ 用于某些任务,因此是可维护的要求。感谢您的投入!
    • Spirit/Qi 是 Boost 中最难理解的部分; Boost 是最难理解的 C++ 库(集合)之一; C++ 是新手比较难理解的语言之一。你选择了一条极其艰难的道路。 :) 我曾在两个完全不同的公司的两个完全不同的项目中尝试在生产代码中使用 Boost Spirit,但每次都在几天后放弃。我不是最好的 C++ 程序员,但在这个早期阶段我比你更擅长,所以我敦促你找到一些其他与 C++ 相关的东西来磨练你的牙齿。
    • 至于普及,Boost是;精神不是。 Boost 中使用较多的部分是 Unordered、Smart Pointers、Regex、Intrusive、Variant、Bind、Filesystem、Program Options 和 Thread。
    猜你喜欢
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 2012-01-17
    • 2011-03-05
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    相关资源
    最近更新 更多