提升精神需要永远解析表达式

时间:2017-01-23 15:05:30

标签: c++ boost runtime expression boost-spirit

我是新来的,与提升精神一起工作

阅读很多非常好的关键词以提升精神我决定制作一个自己的Parser并遇到解析像这样的表达式的问题

1+(2 +(3+(4+(5+(6+(7+(8)))))))

永远在运行时...使它更简单1+(2+(3))工作正常。我看起来像Parser的回溯是活跃的。请给我一个提示,告诉我如何修改语法或行为,以便及时运行。

这是来自语法的位代码。我使用“iter_pos”来跟踪位置。

问候   马库斯

  primary            = functioncall 
                     | constant_double   
                     | constant_integer 
                     | name 
                     | string;

  constant_double   = real_parser< double, strict_ureal_policies<double> >()                    [_val = construct<common_node>(type_const_double, key_value, _1)];
  name              = name_pure_location                                                        [_val = construct<common_node>(type_name, phoenix::bind(&getLocation, _1),key_value, phoenix::bind(&getString, _1))];
  string            = (lexeme[L'"' >> +(boost::spirit::standard_wide::char_ - L'"') >> L'"'])   [_val = construct<common_node>(type_const_string, key_value,phoenix::bind(&makeString, _1))];
  constant_integer  = int_                                                                      [_val = construct<common_node>(type_const_int, key_value, construct<int>(_1))];

  parenthetical =
              lit('(') >> expression >> lit(')')
              | primary;

  unary =
     (iter_pos >> unary_op >> unary >> iter_pos)                            [_val = construct<common_node>(
                                                                                 type_cmd_member_call,
                                                                                 LOCATION(_1,_4),
                                                                                 key_callname, construct<std::wstring>(_2),
                                                                                 key_this,construct<common_node>(_3)
                                                                            )]
    | parenthetical[_val = _1]
    ;

  multiplicative =

    (iter_pos >> unary >> (multiply_op | divide_op | modulo_op) >> multiplicative >> iter_pos)    [_val = construct<common_node>(
                                                                            type_cmd_member_call,
                                                                            LOCATION(_1, _5),
                                                                            key_callname, construct<std::wstring>(_3),
                                                                            key_this, construct<common_node>(_2),
                                                                            key_parameter, construct<common_node>(_4)
                                                                            )]
    | unary[_val = _1];

  additive =

    (iter_pos >> multiplicative >> (add_op | subtract_op) >> additive >> iter_pos) [_val = construct<common_node>(
                                                                                type_cmd_member_call,
                                                                                LOCATION(_1, _5),
                                                                                key_callname, construct<std::wstring>(_3),
                                                                                key_this, construct<common_node>(_2),
                                                                                key_parameter, construct<common_node>(_4)
                                                                              )]
    | multiplicative[_val = _1]
    ;

  compares =

    (iter_pos >> additive >> (compare_op) >> compares >> iter_pos)      [_val = construct<common_node>(
                                                                            type_cmd_member_call,
                                                                            LOCATION(_1, _5),
                                                                            key_callname, construct<std::wstring>(_3),
                                                                            key_this, construct<common_node>(_2),
                                                                            key_parameter, construct<common_node>(_4)
                                                                          )]
    | additive[_val = _1]
    ;

  expression = compares[_val = _1];

2 个答案:

答案 0 :(得分:2)

您正确地找出了问题的根源:规则被指定&#34;懒惰&#34; (因为他们 - 他们应该 - 描述性地给出规则的制作)。

正如你所看到的,在PEG语法中,如果有很多回溯,这很快会导致糟糕的表现。

我已经展示了非常相似表达式的优化。摘要是:而不是&#34;期待&#34;一个二进制表达式和回溯如果事实证明不满足,解析第一个操作数&#34;贪婪&#34;并根据以下内容组成不同的AST表达式节点。

也许有趣:

答案 1 :(得分:0)

这个输入的thx。我尝试你的样本,它的工作方式与预期(和快速)一样..无论如何,我无法使用“Boost :: Spirit:优化表达式解析器”的解决方案与我的语义操作。根本不知道如何将我的行动放入此示例中.. 所有其他链接都是一个重要的来源,我也理解场景背后的想法,但似乎这仍然是PEG语法和回溯的更一般问题的解决方法。那么有更通用的方法来解决这个问题吗?例如。使用“&gt;”运算符而不是“&gt;&gt;”避免在某些时候回溯。到目前为止我没有使用“&gt;”我的样本中的运算符。

在使用链接上的其他信息后,我将规则重写为此规则,现在它可以正常工作。

primary = functioncall | constant_double | constant_integer | name | string;

constant_double = real_parser<double, strict_ureal_policies<double>>()
    [_val = construct<common_node>(type_const_double, key_value, _1)];

name = name_pure_location[_val = construct<common_node>(
                              type_name, phoenix::bind(&getLocation, _1),
                              key_value, phoenix::bind(&getString, _1))];

string = (lexeme[L'"' >> +(boost::spirit::standard_wide::char_ - L'"') >> L'"'])
    [_val = construct<common_node>(type_const_string, key_value,
                                   phoenix::bind(&makeString, _1))];

constant_integer = int_[_val = construct<common_node>(type_const_int, key_value,
                                                      construct<int>(_1))];

parenthetical = lit('(') >> expression >> lit(')') | primary;

// this define is used to make to code more readable ..
#define EXPR_ACTION(NAME)                                                      \
  [_val = construct<common_node>(type_cmd_member_call, LOCATION(_1, _3),       \
                                 key_callname, construct<std::wstring>(NAME),  \
                                 key_this, construct<common_node>(_val),       \
                                 key_parameter, construct<common_node>(_2))]

unary = (iter_pos >> unary_op >> unary >>
         iter_pos)[_val = construct<common_node>(
                       type_cmd_member_call, LOCATION(_1, _4), key_callname,
                       construct<std::wstring>(_2), key_this,
                       construct<common_node>(_3))] 
         | parenthetical[_val = _1];

multiplicative = unary[_val = _1] >> 
           *(iter_pos >> lit('*') >> unary >> iter_pos) EXPR_ACTION(L"_mul") >>
           *(iter_pos >> lit('/') >> unary >> iter_pos) EXPR_ACTION(L"_div");

additive = multiplicative[_val = _1] >>
           *(iter_pos >> lit('-') >> multiplicative >> iter_pos) EXPR_ACTION(L"_sub") >>
           *(iter_pos >> lit('+') >> multiplicative >> iter_pos) EXPR_ACTION(L"_add");

compares =
    additive[_val = _1] >>
    *(iter_pos >> lit('<') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_low") >>
    *(iter_pos >> lit('>') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_gre") >>
    *(iter_pos >> lit('=') >> additive >> iter_pos) EXPR_ACTION(L"_cmp_equ");

logical = compares[_val = _1] >> 
    *(iter_pos >> nocaselit(L"and") >> compares >> iter_pos) EXPR_ACTION(L"_and") >>
    *(iter_pos >> nocaselit(L"or")  >> compares >> iter_pos) EXPR_ACTION(L"_or");

expression = logical[_val = _1];

非常感谢您输入的好消息! 马库斯