yacc中的多个和重新声明的简单语义分析器给出解析错误



这是我为一个简单的语义分析器编写的代码,它只检查重声明和多个声明。这是lex文件

{
#include "y.tab.h"
%}
digits [0-9]*
letters [a-zA-Z]
%%
"for" return FOR;
"if" return IF;
"else" return ELSE;
"while" return WHILE;
"do" return DO;
"switch" return SWITCH;
"case" return CASE;
"break" return BREAK;
"default" return DEFAULT;
"void" return VOID;
"int"  return INT;
"float"  return FLOAT;
"char"  return CHAR;
"double"  return DOUBLE;
"(" return LPAREN;
")" return RPAREN;
"{" return LCURLY;
"}" return RCURLY;
[0-9]+ return INT;
[0-9]*.?[0-9]+|[0-9]+ return FLOAT;
("_")*{letters}("_"|{letters}|{digits})* return alpha;
[a-z]+ return ID;
[ nt] {;}
"+"  return PLUS;
"-"  return MINUS;
"/"  return DIVIDE;
"*"  return MULT;
"^"  return XOR;
"="  return ASSIGN;
"==" return EQUAL;
"++" return INC;
"--" return DEC;
">=" return GE;
"<=" return LE;
">"  return GT;
"<"  return LT;
"!=" return NE;
"&&" return AND;
"||" return OR;
"$"  return END;
","  return COMMA;
";"  return SEMICOLON;
.    return yytext[0];
%%

这是我的yacc文件

%{
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
extern void yyerror(char *);
extern FILE *yyin;
extern int yylineno;
extern char *yytext;
int err_no=0,fl=0,i=0,j=0,type[100];
char symbol[100][100],temp[100];
void insert(int);
%}
%token FOR EQUAL INC DEC alpha num GE LE GT LT NE AND OR END IF ELSE  WHILE DO SWITCH CASE BREAK DEFAULT VOID INT FLOAT CHAR SHORT DOUBLE ID
%token LPAREN RPAREN LCURLY RCURLY COMMA SEMICOLON ASSIGN
%token PLUS MINUS MULT DIVIDE XOR
%left PLUS MINUS MULT DIVIDE
%right ASSIGN
%right XOR
%nonassoc UMINUS
%left LT GT LE GE EQUAL NE
%left AND OR
%start STRT
%%
STRT: S  {return 0;}
;
S: ST S | ST
;

ST:             INT L1 SEMICOLON { printf("Inside int declaration rule");} | FLOAT L2 SEMICOLON | CHAR L3 SEMICOLON | DOUBLE L4 SEMICOLON |INT L1 SEMICOLON ST | FLOAT L2 SEMICOLON ST |
CHAR L3 SEMICOLON ST | DOUBLE L4 SEMICOLON ST;
L1:             L1 COMMA ID {strcpy(temp,(char *)$3); printf("%s", temp); insert(0);}| ID {strcpy(temp,(char *)$1); printf("%s", temp); insert(0);};
L2:             L2 COMMA ID {strcpy(temp,(char *)$3); insert(1);}| ID {strcpy(temp,(char *)$1); insert(1);};
L3:             L3 COMMA ID {strcpy(temp,(char *)$3); insert(2);}| ID {strcpy(temp,(char *)$1); insert(2);};
L4:             L4 COMMA ID {strcpy(temp,(char *)$3); insert(3);}| ID {strcpy(temp,(char *)$1); insert(3);};
%%
void insert(int type1) {
printf("Inside insert function n");
fl=0;
for(j=0;j<i;j++) {
if(strcmp(temp,symbol[j])==0) {
printf("Symbol encountered previously n");
if(type[j]==type1) {
printf("Redeclaration of variable -> %sn",temp);
}
else {
printf("Multiple Declaration of Variablen");
err_no=1;
}
fl=1;
}
}
if(fl==0) {
type[i]=type1;
strcpy(symbol[i],temp);
i++;
}
}

int main(int argc, char **argv){
FILE *fp1;
fp1=fopen(argv[1],"r");
yyin=fp1;
if (yyparse()==0) printf("Parsed Successfully for string %sn", yytext);
else{
printf("nParsing Error at line %d for string %sn", yylineno, yytext);
if(err_no==0) {
//printf("Redeclaration found");
for(j=0;j<i;j++) {
if(type[j]==0) printf("INT ");
if(type[j]==1) printf("FLOAT ");
if(type[j]==2) printf("CHAR ");
if(type[j]==3) printf("DOUBLE ");
printf("%sn",symbol[j]);
}
}
}
return 0;
}
int yywrap(){
return 0;
}
void yyerror(char*s){
printf("Error: %s n", s);
}

输入文件的内容是

int a,b,c;
float a;

我得到错误作为

Error: syntax error 
Parsing Error at line 1 for string a

我最初认为这是由于int和a之间的空格。如果我去掉空格,我会得到以下错误

Error: syntax error 
Parsing Error at line 1 for string inta

我不知道问题出在哪里。我被它卡住了很长一段时间。

编辑修改的规则:

ST:             INT SPACE L1 SEMICOLON { printf("Inside int declaration rule");} | FLOAT SPACE L2 SEMICOLON | CHAR SPACE L3 SEMICOLON | DOUBLE SPACE L4 SEMICOLON |INT SPACE L1 SEMICOLON ST | FLOAT SPACE L2 SEMICOLON ST | CHAR SPACE L3 SEMICOLON ST | DOUBLE SPACE L4 SEMICOLON ST;

修改的输入

int a,a,b,c;

lex文件中有两条规则:

("_")*{letters}("_"|{letters}|{digits})* return alpha;
[a-z]+ return ID;

因为第一条规则会匹配第二条规则所做的一切,所以第二条永远不会匹配。因此,您永远不会得到ID令牌,只有alpha令牌。由于您的语法依赖于ID标记,因此它永远不会匹配。

如果您交换这些行,您将看到与该模式匹配的事物的ID令牌,而只得到与ID规则不匹配的东西的alpha令牌。

最新更新