增强精神永远要解析表情 [英] Boost spirit takes for ever to parse expressions

查看:216
本文介绍了增强精神永远要解析表情的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里工作,在提升精神上



阅读很多非常好的内容,以促进精神我决定制作一个自己的解析器,遇到问题解析表达式如下



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

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



这是一个来自语法的一个代码。我使用iter_pos来跟踪职位。



认罪
Markus

  primary = functioncall 
| constant_double
| constant_integer
|名称
|串;

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

括号=
lit('(')>>表达式>>点亮(')'
| primary;

unary =
(iter_pos>> unary_op>> unary>>  iter_pos)[_val =构造< common_node>(
type_cmd_member_call,
LOCATION(_1,_4),
key_callname,构造< std :: wstring>(_ 2),
key_this,构造< common_node>(_ 3)
)]
|括号[_val = _1]
;

multiplicative =

(iter_pos>> unary>>(multiply_op | divide_op | modulo_op)>>乘法>>  iter_pos)[_val =构造< common_node>(
type_cmd_member_call,
LOCATION(_1,_5),
key_callname,construct< std :: wstring>(_ 3),
key_this,construct< common_node& _2),
key_parameter,构造< common_node>(_ 4)
)]
|一元[_val = _1];

添加=

(iter_pos>>乘法>>(add_op | subtract_op)>>>>>  iter_pos) common_node>(
type_cmd_member_call,
LOCATION(_1,_5),
key_callname,construct< std :: wstring>(_ 3),
key_this,construct< common_node& ,
key_parameter,构造< common_node>(_ 4)
)]
|乘法[_val = _1]
;

compare =

(iter_pos>>>>>(compare_op)>比较>>          (
type_cmd_member_call,
LOCATION(_1,_5),
key_callname,construct< std :: wstring>(_ 3),
key_this,construct< common_node& b $ b key_parameter,构造< common_node>(_ 4)
)]
|加法[_val = _1]
;

表达式=比较[_val = _1];


解决方案

你正确地确定了麻烦的根源:规则被指定为懒惰(因为他们应该 - 描述性地给出规则的制作)。



如您所见,在PEG语法中,这很快导致如果有很多回溯,表现不佳。



我已经显示了非常类似的表达式的优化。总结如下:代替预期二进制表达式和回溯(如果事实证明不满足),请根据以下内容解析第一个操作数grelyily并构成不同的AST表达式节点。





可能有趣:




i am new here working with boost spirit

Reading alot of very good articels for boost Spirit i decide to make an own Parser and run into the Problem that parsing an Expression like this

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

takes forever on runtime.. making it more simple 1+(2+(3)) works fine. I Looks like the backtracking of the Parser is active. Please give me a hint how to modify the grammer or behaviour to make this run in time.

Here is a bit code from the grammer. I use the "iter_pos" for tracking the Position.

regards Markus

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

解决方案

You correctly identified the source of the trouble: the rules are specified "lazily" (in that they - as they should - descriptively give the productions for the rule).

As you can see, in a PEG grammar this quickly leads to a bad performance if there's a lot of backtracking.

I've already shown optimization of very similar expressions. The summary is this: instead of "expecting" a binary expression and backtracking if it turns out not to be satisfied, parse the first operand "greedily" and compose different AST expression nodes depending on what follows.

Perhaps interesting:

这篇关于增强精神永远要解析表情的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆