转变减少YACC中的冲突



我正在尝试以下yacc代码,并接收移位/减少错误。我对这个很陌生

The Purpose of the code is to prepare the syntax for if - else with logical operators also incorporated

%{
#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("nnn Enter the Syntax :  ");
yyparse();
if(syntax_status==1)
{
printf("nnn The Syntax is Correct ");
}
else
{
printf("nnn The Syntax is Imcorrect");
}
return 0;
}
yyerror(char *s)
{
syntax_status=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;}

%%

您需要指定运算符的优先级和关联性:例如,请参阅此处。我引用了教派的话。6

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

%right  '='
%left  '+'  '-'
%left  '*'  '/'
%%
expr    :       expr  '='  expr
|       expr  '+'  expr
|       expr  '-'  expr
|       expr  '*'  expr
|       expr  '/'  expr
|       NAME
;

可以用来构造输入

a  =  b  =  c*d  -  e  -  f*g

如下所示:

a = ( b = ( ((c*d)-e) - (f*g) ) )

必须以类似的方式定义CMP运算符,并且应该对logicop进行划分。为了获得布尔表达式中的常见读数,NOT的行为通常类似于一元减号、AND类*、OR类+。

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 == id是否真的是exp expexp。此外,exp->epsilon规则允许像if(){}这样的表达式,这不是很好。

现在,考虑以下语法:

exp -> exp logicop cmp | cmp
cmp -> rvalue < rvalue | rvalue > rvalue ...
rvalue -> id | num

但也可以这样做:

exp -> exp op exp | rvalue
op -> "||" | "&&" | "<" | ">" ...

后者是传统的方法,但您需要进行语义检查,以确保操作数的类型正确,而以前的语法则在语法层面上确保了这一点。从长远来看(一旦引入布尔变量),第二种方法更可取,因为类型安全是语义问题,而不是语法问题。

另一个注意事项是:空格在您的语言中似乎并不相关,但lex正在将它们交给yacc。你可以让lex在词汇层面上放弃空格,方法是说

{space} //nothing after a pattern discards the matched characters

这将省去在yacc中写出所有SP的麻烦。

相关内容

  • 没有找到相关文章

最新更新