Bison 野牛转移/减少冲突
我试图描述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
%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将尝试使用优先规则解决该冲突。特别是