Compiler construction 减少YACC中的冲突

Compiler construction 减少YACC中的冲突,compiler-construction,if-statement,yacc,shift-reduce-conflict,Compiler Construction,If Statement,Yacc,Shift Reduce Conflict,我正在尝试下面的yacc代码,并收到shift/reduce错误。我对这个很陌生 该代码的目的是准备if-else的语法,其中还包含逻辑运算符 %{ #include<stdio.h> #include"lex.yy.c" int syntax_status=0; %} %token IF ELS id EE LE GE clos

我正在尝试下面的yacc代码,并收到shift/reduce错误。我对这个很陌生

该代码的目的是准备if-else的语法,其中还包含逻辑运算符

           %{
               #include<stdio.h>
               #include"lex.yy.c"
               int syntax_status=0;
           %}
           %token IF ELS id EE LE GE closep openp num openb closeb SP logicop 
           %start S
           %%
           S : S SP IF SP openp SP EXP SP closep SP openb SP closeb SP ELS SP openb SP closeb SP {syntax_status=1;}
             | S SP IF SP openp SP EXP SP closep SP openb SP closeb SP {syntax_status = 1;}
             | 
             ;
         EXP : EXP CMP logicop CMP
             | EXP CMP
             |
             ;
         CMP : CMP id EE id 
             | CMP id LE id
             | CMP id GE id
             | CMP id EE num
             | CMP id GE num
             | CMP id LE num
             | CMP num EE id
             | CMP num GE id
             | CMP num LE id
             | 
             ;
         %%
         int main()
         {
              printf("\n\n\n Enter the Syntax :  ");
              yyparse();
              if(syntax_status==1)
              {
                     printf("\n\n\n The Syntax is Correct ");
              }
              else
              {
                     printf("\n\n\n The Syntax is Imcorrect");
              }
              return 0;
          }
          yyerror(char *s)
          {
              syntax_status=0;
          }
%{
#包括
#包括“lex.yy.c”
int syntax_status=0;
%}
%如果ELS id EE LE GE closep openp num openb closeb SP logicop
%开始
%%
S:S SP如果SP openp SP EXP SP closep SP openb SP closeb SP ELS SP openb SP closeb SP{syntax_status=1;}
|如果SP openp SP EXP SP closep SP openb SP closeb SP{syntax_status=1;}
| 
;
EXP:EXP CMP logicop CMP
|EXP CMP
|
;
CMP:CMP-id-EE-id
|CMP-id-LE-id
|CMP id GE id
|CMP-id-EE-num
|CMP-id-GE-num
|CMP-id-LE-num
|CMP num EE id
|CMP数GE id
|CMP数字LE id
| 
;
%%
int main()
{
printf(“\n\n\n输入语法:”);
yyparse();
如果(语法_状态==1)
{
printf(“\n\n\n语法正确”);
}
其他的
{
printf(“\n\n\n语法不正确”);
}
返回0;
}
yyerror(字符*s)
{
语法_状态=0;
}
此对应yacc代码的Lex程序如下所示:

           %{
              #include<stdio.h>
              #include"y.tab.h"
           %}
           IF (if)
           ELS (else)
           iden [a-zA-Z][a-zA-Z0-9]*
           num [0-9]+
           space [ ]* 
           %%
           {IF} { return IF; }
           {ELS} {return ELSE;}
           {iden} {return id;}
           (==) {return EE;}
           (<=) { return LE;}
           (>=) { return GE;}
           ")" { return closep;}
           "(" { return openp;}
          {num} { return num;}
          {space} { return SP; }
          "{" { return openb;}
          "}" { return closeb;}
          "||"|"&&"|"!=" {return logicop;}
%{
#包括
#包括“y.tab.h”
%}
如果(如果)
ELS(其他)
同上[a-zA-Z][a-zA-Z0-9]*
数值[0-9]+
空格[]*
%%
{IF}{return IF;}
{ELS}{return ELSE;}
{iden}{return id;}
(==){返回EE;}
(=){return GE;}
“{return closep;}”
(“{return openp;}
{num}{return num;}
{space}{return SP;}
{{return openb;}
“}”{return closeb;}
“| |”&&&“|”!=”{return logicop;}

%%

您需要指定运算符的优先级和关联性:例如,请参见第6节中的引用

作为这些声明行为的示例,描述

可能用于构造输入

    a  =  b  =  c*d  -  e  -  f*g
详情如下:

    a = ( b = ( ((c*d)-e) - (f*g) ) )
您的
CMP
运算符必须以类似的方式定义,并且您的
logicop
应该被除法。要获得布尔表达式中的常规读数,通常不会表现为一元负号、like*、like+


HTH

CMP和EXP规则看起来都很有问题。以最右边的派生为例:

 EXP ==> (by EXP -> CMP)
 EXP CMP ==>  (by CMP -> CMP id EE id)
 EXP CMP id EE id ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id id EE id ==> (by CMP -> epsilon)
 EXP id EE id id EE id ==> (by EXP -> epsilon )
 id EE id id EE id ==>
 id == id id == id
我很确定这不是你想要的。这也给语法带来了歧义:相同的终端字符串可以通过不同的最右边派生得到:

 EXP ==> (by EXP -> CMP)
 EXP CMP ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id ==> (by CMP -> epsilon)
 EXP id EE id ==> (by EXP -> CMP)
 EXP CMP id EE id ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id id EE id ==> (by CMP -> epsilon)
 EXP id EE id  id EE id ==> (by EXP-> epsilon)
 id EE id  id EE id ==>
 id == id id == id
你看,yacc将无法知道
id==id==id
是否真的是
exp
exp
。此外,exp->epsilon规则允许像
if(){}
这样的表达式,这不是很好

现在,考虑下面的语法:

 exp -> exp logicop cmp | cmp
 cmp -> rvalue < rvalue | rvalue > rvalue ...
 rvalue -> id | num
这将使您省去在yacc中写出所有这些SP的麻烦

 exp -> exp logicop cmp | cmp
 cmp -> rvalue < rvalue | rvalue > rvalue ...
 rvalue -> id | num
exp -> exp op exp | rvalue
op -> "||" | "&&" | "<" | ">" ...
{space} //nothing after a pattern discards the matched characters