我是新来的,与提升精神一起工作
阅读很多非常好的关键词以提升精神我决定制作一个自己的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];
答案 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];
非常感谢您输入的好消息! 马库斯