Parsing 试图找到移位/减少语法冲突
我有以下语法(Yacc),这是一个简单C编译器的开始,我从一个简单的Parsing 试图找到移位/减少语法冲突,parsing,compilation,grammar,bison,yacc,Parsing,Compilation,Grammar,Bison,Yacc,我有以下语法(Yacc),这是一个简单C编译器的开始,我从一个简单的if语句开始: S : E ; E : COND_NO_ELSE ; COND_NO_ELSE : IF BOOL_EXP BLOCK ; BLOCK : LC EXP RC BOOL_EXP : LP EXP BOOL_OP EXP RP ; BOOL_OP : LT_OP | GT_OP | LE_OP | GE_OP | EQ_OP | NE_O
if
语句开始:
S : E
;
E : COND_NO_ELSE
;
COND_NO_ELSE : IF BOOL_EXP BLOCK
;
BLOCK : LC EXP RC
BOOL_EXP : LP EXP BOOL_OP EXP RP
;
BOOL_OP : LT_OP
| GT_OP
| LE_OP
| GE_OP
| EQ_OP
| NE_OP
;
MATH_OP : PLUS_OP
;
EXP : IDENTIFIER
| EXP MATH_OP EXP
;
以下是相关规则的词法分析器扫描程序:
"=" { yylval.string = strdup(yytext); return ASSIGN;}
"+" { yylval.string = strdup(yytext); return PLUS_OP;}
"-" { yylval.string = strdup(yytext); return MINUS_OP;}
"*" { yylval.string = strdup(yytext); return MULTIPLY_OP;}
"/" { yylval.string = strdup(yytext); return DIV_OP;}
"%" { yylval.string = strdup(yytext); return MOD_OP;}
"<" { yylval.string = strdup(yytext); return LT_OP;}
">" { yylval.string = strdup(yytext); return GT_OP; }
"<=" { yylval.string = strdup(yytext); return LE_OP; }
">=" { yylval.string = strdup(yytext); return GE_OP; }
"==" { yylval.string = strdup(yytext); return EQ_OP; }
"!=" { yylval.string = strdup(yytext); return NE_OP; }
"(" { yylval.string = strdup(yytext); return LP; }
")" { yylval.string = strdup(yytext); return RP; }
"{" { yylval.string = strdup(yytext); return LC; }
"}" { yylval.string = strdup(yytext); return RC; }
if { return IF; }
“=”{yylval.string=strdup(yytext);返回ASSIGN;}
“+”{yylval.string=strdup(yytext);返回加号_OP;}
“-”{yylval.string=strdup(yytext);返回减号_OP;}
“*”{yylval.string=strdup(yytext);返回乘法运算;}
“/”{yylval.string=strdup(yytext);返回DIV_OP;}
“%”{yylval.string=strdup(yytext);返回MOD_OP;}
“{yylval.string=strdup(yytext);返回GT_OP;}”
“=”{yylval.string=strdup(yytext);返回GE_OP;}
“=”{yylval.string=strdup(yytext);返回EQ_OP;}
“!=”{yylval.string=strdup(yytext);返回NE_OP;}
(“{yylval.string=strdup(yytext);返回LP;}
“{yylval.string=strdup(yytext);返回RP;}”
{{yylval.string=strdup(yytext);返回LC;}
“}”{yylval.string=strdup(yytext);返回RC;}
if{返回if;}
我确实知道,当我添加MATH_OP
时,冲突就开始了(我的所有数学运算符都大于,得到了5个冲突,除了PLUS_OP
之外,我删除了所有运算符,得到了1个shift/reduce冲突)
我按照建议为输出文件使用了-v
标志,并检查了问题,但它与我的语法不太相似
如何找到冲突?您的语法包括生产:
EXP : EXP MATH_OP EXP
这本身就是模棱两可的。假设您有两个运算符:
1 + 2 * 3
显然,上面是EXP MATH\u OP EXP
(因为没有其他选项),但是
[EXP: 1 + 2] [MATH_OP *] [EXP: 3]
还是这样
[EXP: 1] [MATH_OP +] [EXP: 2 * 3]
这两种语法显然具有不同的语义,语法允许这两种语法
即使只有一个运算符,也会有歧义(事实上,是相同的歧义),尽管在+的通常定义中,计算结果是相同的。(与单个运算符不同,这使得模糊性稍微清晰一些。)
为算术表达式创建yacc/bison语法有两种常见策略:
MATH_OP
)中,因为具有不同前导的运算符在语法上是不同的
你也可以在这个网站上找到很多相关的问题和答案
顺便说一下,将纯语法标记(如
+
)的字符串值传递给解析器很少有用。解析器不需要该值,因为它已经知道令牌类型,因此strdup()
是不必要的开销,而相应的free()
会使语法操作变得杂乱无章(同样,放在哪里也不明显)。如果您认为需要字符串来跟踪语法动作,那么请检查哪些比在整个解析器中使用printfs更容易使用和更可靠。如果您根本不使用运算符的语义值,那么显然不需要麻烦复制字符串,然后释放或泄漏内存。您的语法包括以下内容:
EXP : EXP MATH_OP EXP
这本身就是模棱两可的。假设您有两个运算符:
1 + 2 * 3
显然,上面是EXP MATH\u OP EXP
(因为没有其他选项),但是
[EXP: 1 + 2] [MATH_OP *] [EXP: 3]
还是这样
[EXP: 1] [MATH_OP +] [EXP: 2 * 3]
这两种语法显然具有不同的语义,语法允许这两种语法
即使只有一个运算符,也会有歧义(事实上,是相同的歧义),尽管在+的通常定义中,计算结果是相同的。(与单个运算符不同,这使得模糊性稍微清晰一些。)
为算术表达式创建yacc/bison语法有两种常见策略:
MATH_OP
)中,因为具有不同前导的运算符在语法上是不同的
你也可以在这个网站上找到很多相关的问题和答案
顺便说一下,将纯语法标记(如
+
)的字符串值传递给解析器很少有用。解析器不需要该值,因为它已经知道令牌类型,因此strdup()
是不必要的开销,而相应的free()
会使语法操作变得杂乱无章(同样,放在哪里也不明显)。如果您认为需要字符串来跟踪语法动作,那么请检查哪些比在整个解析器中使用printfs更容易使用和更可靠。如果您根本不使用运算符的语义值,那么显然不需要麻烦地复制字符串,然后释放或l