优先权问题

时间:2017-11-01 10:01:24

标签: parsing bison bisonc++

我尝试为相对简单的语法生成解析器,但我无法正常工作。

我设法降低了15个班次/减少错误,但我不知道如何解决这些剩下的几个问题 - 而且他们可能与我的优先问题有关。

我的语法定义如下:

%nonassoc T_LEN T_OPENPAREN T_CLOSEPAREN T_NUM T_ID T_QUOTE T_TRUE T_FALSE
%left T_GT T_GTE T_LT T_LTE T_EQ
%left T_OR
%left T_AND
%left T_NOT

Start           : Expression                                    { astRoot = new MainNode( $1 ); }
                ;

Expression      : Expression T_OR Expression                    { $$ = new OrNode( $1, $3 ); }
                | Expression T_AND Expression                   { $$ = new AndNode( $1, $3 ); }
                | Expression Expression                         { $$ = new AndNode( $1, $2 ); }
                | T_NOT Expression                              { $$ = new NotNode( $2 ); }
                | T_GT Expression                               { $$ = new GreaterNode( $2 ); }
                | T_GTE Expression                              { $$ = new GreaterEqualNode( $2 ); }
                | T_LT Expression                               { $$ = new LessNode( $2 ); }
                | T_LTE Expression                              { $$ = new LessEqualNode( $2 ); }
                | T_EQ Expression                               { $$ = new EqualNode( $2 ); }
                | T_LEN T_OPENPAREN T_NUM T_CLOSEPAREN          { $$ = new LenNode( new IntegerNode( $3 ) ); }
                | T_OPENPAREN Expression T_CLOSEPAREN           { $$ = $2; }
                | T_TRUE                                        { $$ = new BoolTrueNode; }
                | T_FALSE                                       { $$ = new BoolFalseNode; }
                | T_ID                                          { $$ = new IdentifierNode( $1 ); }
                | T_NUM                                         { $$ = new IntegerNode( $1 ); }
                | T_QUOTE                                       { $$ = new QuoteNode( new IdentifierNode( $1 ) ); }
                ;

当试图解析以下内容时,我没有得到我想要的值:

100 T_AND 200 T_AND 300 T_AND 400 T_OR 1000
output => And( "100", And( "200", And( "300", Or( "400", "1000" ) ) ) );
expect => Or( And( "100", And( "200", And( "300", "400" ) ) ), "1000" );

最后,我的解析器输出的相关部分是:

State 27 conflicts: 15 shift/reduce

0 $accept: Start $end

1 Start:       Expression

2 Expression:  Expression T_OR Expression
3            | Expression T_AND Expression
4            | Expression Expression
5            | T_NOT Expression
6            | T_GT Expression
7            | T_GTE Expression
8            | T_LT Expression
9            | T_LTE Expression
10           | T_EQ Expression
11           | T_LEN T_OPENPAREN T_NUM T_CLOSEPAREN
12           | T_OPENPAREN Expression T_CLOSEPAREN
13           | T_TRUE
14           | T_FALSE
15           | T_ID
16           | T_NUM
17           | T_QUOTE

State 27

    2 Expression: Expression . T_OR Expression
    3           | Expression . T_AND Expression
    4           | Expression . Expression
    4           | Expression Expression .

    T_LEN        shift, and go to state 1
    T_OPENPAREN  shift, and go to state 2
    T_NUM        shift, and go to state 3
    T_ID         shift, and go to state 4
    T_QUOTE      shift, and go to state 5
    T_TRUE       shift, and go to state 6
    T_FALSE      shift, and go to state 7
    T_GT         shift, and go to state 8
    T_GTE        shift, and go to state 9
    T_LT         shift, and go to state 10
    T_LTE        shift, and go to state 11
    T_EQ         shift, and go to state 12
    T_OR         shift, and go to state 25
    T_AND        shift, and go to state 26
    T_NOT        shift, and go to state 13

    T_LEN        [reduce using rule 4 (Expression)]
    T_OPENPAREN  [reduce using rule 4 (Expression)]
    T_NUM        [reduce using rule 4 (Expression)]
    T_ID         [reduce using rule 4 (Expression)]
    T_QUOTE      [reduce using rule 4 (Expression)]
    T_TRUE       [reduce using rule 4 (Expression)]
    T_FALSE      [reduce using rule 4 (Expression)]
    T_GT         [reduce using rule 4 (Expression)]
    T_GTE        [reduce using rule 4 (Expression)]
    T_LT         [reduce using rule 4 (Expression)]
    T_LTE        [reduce using rule 4 (Expression)]
    T_EQ         [reduce using rule 4 (Expression)]
    T_OR         [reduce using rule 4 (Expression)]
    T_AND        [reduce using rule 4 (Expression)]
    T_NOT        [reduce using rule 4 (Expression)]
    $default     reduce using rule 4 (Expression)

    Expression  go to state 27

我能理解的最好的问题可能是隐含的和(规则3和4)引起的问题。如果这是问题的根源,我该如何解决它?

谢谢!

1 个答案:

答案 0 :(得分:0)

在写这个问题的时候,我只是意识到隐含的,可能是问题的根源。现在,通过更加扎实地理解可能出现的问题,我能够编写正确的Google查询,引导我this post

在阅读答案之后,解决方案刚刚落实到位。我通过语法选择了明确的优先级,而不是通过bison的优先级声明来隐式优先级。这给了我以下语法:

Start           : Expression                                    { astRoot = new MainNode( $1 ); }
                ;

Term            : T_TRUE                                        { $$ = new BoolTrueNode; }
                | T_FALSE                                       { $$ = new BoolFalseNode; }
                | T_ID                                          { $$ = new IdentifierNode( $1 ); }
                | T_NUM                                         { $$ = new IntegerNode( $1 ); }
                | T_QUOTE                                       { $$ = new QuoteNode( new IdentifierNode( $1 ) ); }
                | T_LEN T_OPENPAREN T_NUM T_CLOSEPAREN          { $$ = new LenNode( new IntegerNode( $3 ) ); }
                | T_OPENPAREN Expression T_CLOSEPAREN           { $$ = $2; }
                ;

Prefix          : Term
                | T_NOT Prefix                                  { $$ = new NotNode( $2 ); }
                | T_GT Term                                     { $$ = new GreaterNode( $2 ); }
                | T_GTE Term                                    { $$ = new GreaterEqualNode( $2 ); }
                | T_LT Term                                     { $$ = new LessNode( $2 ); }
                | T_LTE Term                                    { $$ = new LessEqualNode( $2 ); }
                | T_EQ Term                                     { $$ = new EqualNode( $2 ); }
                ;

Factor          : Prefix
                | Prefix Factor                                 { $$ = new AndNode( $1, $2 ); }
                ;

Andor           : Factor
                | Andor T_AND Factor                            { $$ = new AndNode( $1, $3 ); }
                ;

Expression      : Andor
                | Expression T_OR Andor                         { $$ = new OrNode( $1, $3 ); }
                ;

这给了我0个转移/减少冲突以及到目前为止我在所有测试中所期望的值。同样以这种方式安排我的语法会使语言的细微差别显而易见,例如以下陈述的有效性:

T_NOT T_GT 100 => Not( Greater( "100" ) ) => valid
T_GT T_NOT 100 => Greater( Not( "100" ) ) => invalid

除非有人发现我提出的语法存在任何隐藏的问题,否则我相信这完全解决了我的问题。