Bison 野牛转移/减少冲突

Bison 野牛转移/减少冲突,bison,shift-reduce-conflict,Bison,Shift Reduce Conflict,我试图描述Bison输入文件的以下语法: 这是我的意见: %start Program %token KW_CLASS KW_EXTENDS KW_PUBLIC KW_STATIC KW_BOOLEAN KW_STRING KW_FLOAT KW_INT EOF %token KW_IF KW_WHILE KW_BREAK KW_CONTINUE KW_SWITCH KW_CASE KW_DEFAULT KW_RETURN %token KW_NEW KW_THIS KW_NULL KW_TR

我试图描述Bison输入文件的以下语法:

这是我的意见:

%start Program
%token KW_CLASS KW_EXTENDS KW_PUBLIC KW_STATIC KW_BOOLEAN KW_STRING KW_FLOAT KW_INT EOF
%token KW_IF KW_WHILE KW_BREAK KW_CONTINUE KW_SWITCH KW_CASE KW_DEFAULT KW_RETURN
%token KW_NEW KW_THIS KW_NULL KW_TRUE KW_FALSE KW_PRINTLN
%token IDENT INT_LITERAL FLOAT_LITERAL STRING_LITERAL

%nonassoc "THEN"
%nonassoc KW_ELSE

%right "STATEMENTS"

%right OP_ASSIGN
%left OP_OR
%left OP_AND
%nonassoc CMP_EQ CMP_NEQ
%nonassoc CMP_GT CMP_LT CMP_GTE CMP_LTE
%left OP_ADD OP_MINUS
%left OP_MULT OP_DIV OP_MOD
%right OP_NOT OP_UNARY "NEW" 
%left "FUNCALL" "SUBSCRIPT"  '.'
%nonassoc '('
%nonassoc ')'
%%
Program:        ClassDeclp EOF
            ;

ClassDeclp:     ClassDecl
            | ClassDeclp ClassDecl
            ;
ClassDecl:      KW_CLASS IDENT ExtendsFrom
            '{' VarDecls MethodDecls '}'
            ;
ExtendsFrom:        /*empty*/
                | KW_EXTENDS IDENT
            ;

VarDecls:       /*empty*/
            | VarDecls VarDecl
            ;
VarDecl:        Type IDENT ';'
            | KW_STATIC Type IDENT ';' /*Co the sua thanh AcessModifier Type IDENT*/
            ;

MethodDecls:        /*empty*/
            | MethodDecls MethodDecl
            ;
MethodDecl:     KW_PUBLIC Type IDENT
            '('MethodParams')'
            '{'VarDecls Statements KW_RETURN Expression ';' '}'
            ;

MethodParams:       /*empty*/
            | MethodParams ',' MethodParam
            ;       
MethodParam:        Type IDENT;

Type :          Type '['']'
                | KW_BOOLEAN
            | KW_STRING
            | KW_FLOAT
            | KW_INT
            | IDENT
            ;
Statements:     Statements Statement    %prec "STATEMENTS"
            | /*empty*/ %prec "STATEMENT"
            ;
Statementp:     Statements Statement %prec "STATEMENTS"
            ;
Statement:      '{'Statements'}'
            | KW_IF '(' Expression ')' Statement %prec "THEN"
            | KW_IF '(' Expression ')' Statement KW_ELSE Statement
            | KW_WHILE '(' Expression ')'Statement
            | KW_PRINTLN '(' Expression ')' ';'
            | IDENT OP_ASSIGN Expression ';'
            | KW_BREAK ';'
            | KW_CONTINUE ';'
            | IDENT %prec "SUBSCRIPT" '['Expression']' '=' Expression ';'
            | KW_SWITCH '(' Expression ')' '{'
              Cases
              KW_DEFAULT ':' Statementp '}'
            ;

Cases:          Cases Case
            | /*empty*/
            ;
Case:           KW_CASE INT_LITERAL ':' Statementp
            ;


Expression:     Expression OP_OR Expression
            | Expression OP_AND Expression
            | Expression CMP_EQ Expression
            | Expression CMP_NEQ Expression
            | Expression CMP_GT Expression
            | Expression CMP_GTE Expression
            | Expression CMP_LT Expression
            | Expression CMP_LTE Expression
            | Expression OP_ADD Expression
            | Expression OP_MINUS Expression
            | Expression OP_MULT Expression
            | Expression OP_DIV Expression
            | Expression OP_MOD Expression
            | '-' Expression %prec OP_UNARY
            | OP_NOT Expression
            | Expression %prec "SUBSCRIPT" '['Expression']'
            | Expression '.'"length"
            | Expression '.' IDENT %prec "FUNCALL" '(' ParamList ')' 
            | INT_LITERAL
            | FLOAT_LITERAL
            | STRING_LITERAL
            | KW_NULL
            | KW_TRUE
            | KW_FALSE
            | IDENT
            | KW_THIS
            | KW_NEW Type '[' Expression ']' %prec "NEW"
            | KW_NEW IDENT '('')'        %prec "NEW"
            | '(' Expression ')'
            ;


ParamList:      /*empty*/
            | ParamList ',' Expression
            | Expression
            ;
%%
main(int argc, char** argv[])
{
    extern FILE *yyin;
    ++argv; --argc;
    yyin = fopen(argv[0], "r");
    yydebug = 1;
    errors = 0;
    yyparse();
}

yyerror(char *s)
{
    printf("%s\n", s);
}

/* Co 3 conflict RR can xu ly khi bien thuoc kieu bool
   giua BoolExpr va Expresstion */
编译时我遇到了两个16冲突。 其中一个冲突是,我用--report=lookahead运行野牛:

OP_不是表达式。[OP_OR,OP_AND,CMP_EQ,CMP_NEQ,CMP_GT,CMP_LT,CMP_GTE,CMP_LTE,OP_ADD,OP_-MINUS,OP_-MULT,OP_-DIV,OP_-MOD'),,,,,,,,,,[,]

我所期望的是“[”不在OP_not lookahead token中,因为下标优先级必须高于运算符!。 其他冲突都是这样的,我怎么解决呢。
Tks

优先级不是这样工作的

编辑:如果你发现下面的描述令人困惑,或者你不想费力阅读这么多的英文文本,你可以接受我的建议:不要使用优先级。你几乎可以编写一个不需要优先级声明的明确语法。如果你这样做,你就不需要理解优先级。(不过,老实说,如果您了解LR解析的工作原理,就不会那么复杂了。)/EDIT

优先级总是比较可能的缩减(即右手边与当前解析器堆栈顶部匹配的产品)和先行符号

在这一点上:

Expression : Expression · '[' Expression ']'
惟一可能的解析器操作是移位,因为只有当该点位于右侧的末尾时,才会发生缩减

但是,在该点出现的一种状态下,还有另一种生产:

Expression : OP_NOT Expression ·
这一点可以减少,因为该点位于末尾

由于这两个点处于相同的状态,它们必须都有效。这意味着我们正在研究:

OP_NOT Expression · '[' Expression ']'
我们正在努力想办法。我们可以将
OP_NOT Expression
简化为
Expression
,此时我们将:

Expression · '[' Expression ']'
或者我们可以改变“[”,留下

OP_NOT Expression '[' · Expression ']'
由于这两个都是可能的,因此存在移位/减少冲突。如果存在优先规则,Yacc/Bison将尝试使用优先规则解决该冲突。特别是,它需要比较可能减少的生产的优先顺序:

Expression : OP_NOT Expression
以及可能移位的符号:
“[”

但是,仔细查看优先级声明后发现,
'['
没有指定优先级。因此,yacc/bison无法对产品进行测试(其优先级由右侧的最后一个终端定义,
OP\u NOT
),因为没有
%prec
声明

如果希望后缀下标运算符(
[
表达式']')的优先级高于前缀运算符
OP\u NOT
,则必须为
[
声明高于
OP\u NOT
的优先级

顺便说一句,我看不出这里有什么不一致的地方。你可以用
来表示
OP\u NOT
(和
-
表示
OP\u减
等等),这样更容易阅读,工作量更少

您似乎认为
%prec
声明

Expression %prec "SUBSCRIPT" '['Expression']'
是相关的。它不是。它仅在解析器可以减少
表达式“['Expression']”时才适用。但它也是毫无意义的,因为您不需要创建伪终端来保持该产品的优先级;它的优先级由右侧的最后一个终端定义,
']“
,因此您可以为该终端声明优先级

声明
Expression:OP\u减号表达式%prec OP\u一元
中的伪标记是必需的,因为
'-'
有两个不同的先例,或者更准确地说,因为
OP\u减号表达式
Expresson OP\u减号表达式
具有不同的优先级您可以使用任何具有正确优先级的标记,例如
OP\u NOT
OP\u NEW

如果这还不够用的话,我试着用几个不同的SO答案来解释这一点。还有,这是中的文档。如果你幸运的话,你可以用自己的语言找到一个描述,使用任何对你最合适的互联网搜索引擎,或者与你的教授交谈(如果你有)


顺便说一下,前瞻报告会告诉您哪些符号可能跟在给定的产品后面。优先级对此没有影响。
[
绝对可以跟随
!a
。优先级告诉解析器是减少还是移位,但可能触发减少或移位的标记肯定在前瞻集中。

优先级不是这样工作的

编辑:如果你发现下面的描述令人困惑,或者你不想费力阅读这么多的英文文本,你可以接受我的建议:不要使用优先级。你几乎可以编写一个不需要优先级声明的明确语法。如果你这样做,你就不需要理解优先级。(不过,老实说,如果您了解LR解析的工作原理,就不会那么复杂了。)/EDIT

优先级总是比较可能的缩减(即右手边与当前解析器堆栈顶部匹配的产品)和先行符号

在这一点上:

Expression : Expression · '[' Expression ']'
惟一可能的解析器操作是移位,因为只有当该点位于右侧的末尾时,才会发生缩减

但是,在该点出现的一种状态下,还有另一种生产:

Expression : OP_NOT Expression ·
这一点可以减少,因为该点位于末尾

由于这两个点处于相同的状态,它们必须都有效。这意味着我们正在研究:

OP_NOT Expression · '[' Expression ']'
我们正在努力想办法。我们可以将
OP_NOT Expression
简化为
Expression
,此时我们将:

Expression · '[' Expression ']'
或者我们可以改变“[”,留下

OP_NOT Expression '[' · Expression ']'
由于这两个都是可能的,因此存在移位/减少冲突。如果存在优先规则,Yacc/Bison将尝试使用优先规则解决该冲突。特别是