这是我为一个简单的语义分析器编写的代码,它只检查重声明和多个声明。这是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
令牌。