gpt4 book ai didi

c++ - BOOST_SPIRIT_DEFINE 不明白

转载 作者:行者123 更新时间:2023-12-04 08:19:16 25 4
gpt4 key购买 nike

我正在尝试用 boost spirit x3 编写一个表达式解析器。
我的新代码基于我多年前用 Spirit 2.x (qi) 编写(并且运行良好)的旧代码。
我的代码的核心是:

   //Make new rule(s) for expression
auto term = factor >> *(('*' >> factor) | ('/' >> factor));
auto expression = term >> *(('+' >> term) | ('-' >> term));
auto group = '(' >> expression >> ')';
auto factor = lexeme["double_"] | group;


string s="12.4 + 3.2";

auto first = s.begin();
auto last = s.end();
bool r = x3::phrase_parse(
first,
last,
// Begin grammar
expression,
// End grammar
x3::space);
我收到两个错误(Visual Studio 2019):
错误 C2338 BOOST_SPIRIT_DEFINE 未为此规则定义。
错误 C2039“解析”:不是“boost::spirit::x3::unused_type”的成员
为什么?

最佳答案

BOOST_SPIRIT_DEFINE 用于将静态规则标签与定义(即该规则的解析函数模板的实例化)相关联。
好消息是这通常是不必要的,并且可以在没有任何宏的情况下内嵌定义规则。
一般来说,使用x3::rule存在以下原因:

  • 当规则使用递归时。递归调用的规则需要有未定义的规则(未初始化的 rule<> 对象)来引用(很像前向声明)。
  • 强制暴露的属性类型(根据我的经验,在 X3 中比在 Qi 中更常见: Understanding the List Operator (%) in Boost.Spirit ,或例如 boost::spirit::x3 attribute compatibility rules, intuition or code? )。
  • 当您想在翻译单元之间传播规则定义时(即具有外部定义)。请注意,这还要求您了解需要支持的上下文和迭代器类型,以便您可以适本地实例化。
  • 受益于内置规则调试( #define BOOST_SPIRIT_X3_DEBUG )。这是我知道使用 BOOST_SPIRIT_DEFINE 的唯一原因宏家族

    This frequently gives rise to hard-to diagnose linker errors so I recommend against this in most cases: X3 parsers compile fast enough in practice that I can afford to keep them in a single translation unit



  • 您的 sample
    只有 expression递归使用。对于其余的,只需重新排序它们就足够了:
    namespace parser {
    x3::rule<struct expression_> expression{"expression"};

    auto group = '(' >> expression >> ')';
    auto factor = x3::lexeme["double_"] | group;
    auto term = factor >> *(('*' >> factor) | ('/' >> factor));
    auto expression_def = term >> *(('+' >> term) | ('-' >> term));

    BOOST_SPIRIT_DEFINE(expression)
    }
    看看 Live On Compiler Explorer 打印:
    <expression>
    <try>12.4 + 3.2</try>
    <fail/>
    </expression>
    ------ 12.4 + 3.2
    r: false
    remaining input: '12.4 + 3.2'
    很明显,您的 factor规则应该恢复正常:
    auto factor         = x3::double_ | group;
    看看 Live On Compiler Explorer 打印:
    <expression>
    <try>12.4 + 3.2</try>
    <success></success>
    </expression>
    ------ 12.4 + 3.2
    r: true
    remaining input: ''
    奖励:属性
    添加属性传播将突出我在上面 2. 下的意思:
    namespace Ast {
    struct binop;

    using expression = boost::make_recursive_variant<
    double,
    boost::recursive_wrapper<binop>,
    boost::recursive_variant_
    >::type;

    struct binop {
    char op;
    expression lhs, rhs;
    };
    }
    这是可以工作的最简单的事情。您的规则对于从语义操作构建 ast 非常有效¹:
    namespace parser {
    x3::rule<struct expression_, Ast::expression> expression{"expression"};

    auto assign = [](auto& ctx) { _val(ctx) = _attr(ctx); };
    auto make_binop = [](auto& ctx) {
    using boost::fusion::at_c;
    auto& op = at_c<0>(_attr(ctx));
    auto& rhs = at_c<1>(_attr(ctx));
    _val(ctx) = Ast::binop { op, _val(ctx), rhs };
    };

    auto group
    = x3::rule<struct group_, Ast::expression> {"group"}
    = '(' >> expression >> ')';

    auto factor
    = x3::rule<struct factor_, Ast::expression> {"factor"}
    = x3::double_ | group;

    auto term
    = x3::rule<struct term_, Ast::expression> {"term"}
    = factor [assign] >> *(x3::char_("*/") >> factor) [make_binop];

    auto expression_def
    = term [assign] >> *(x3::char_("-+") >> term) [make_binop];

    BOOST_SPIRIT_DEFINE(expression)
    }
    看看 Live On Compiler Explorer :
    int main() {
    for (std::string const s : {
    "12.4 + 3.2",
    })
    {
    auto f = s.begin(), l = s.end();
    Ast::expression e;
    bool r = x3::phrase_parse(f, l, parser::expression, x3::space, e);

    std::cout
    << "------ " << s << "\n"
    << "r: " << std::boolalpha << r << "\n";

    if (r)
    std::cout << "e: " << e << "\n";

    if (f!=l)
    std::cout << "remaining input: '" << std::string(f,l) << "'\n";
    }
    }
    打印
    ------ 12.4 + 3.2
    r: true
    e: (12.4 + 3.2)
    和调试输出:
    <expression>
    <try>12.4 + 3.2</try>
    <term>
    <try>12.4 + 3.2</try>
    <factor>
    <try>12.4 + 3.2</try>
    <success> + 3.2</success>
    <attributes>12.4</attributes>
    </factor>
    <success> + 3.2</success>
    <attributes>12.4</attributes>
    </term>
    <term>
    <try> 3.2</try>
    <factor>
    <try> 3.2</try>
    <success></success>
    <attributes>3.2</attributes>
    </factor>
    <success></success>
    <attributes>3.2</attributes>
    </term>
    <success></success>
    <attributes>(12.4 + 3.2)</attributes>
    </expression>

    ¹ 这里我没有提到 my usual screed因为在这种语法中使用自动传播往往会导致语法中出现大量的回溯,从而导致效率低下

    关于c++ - BOOST_SPIRIT_DEFINE 不明白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65566480/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com