【问题标题】:Simple semantic analyser for multiple and redeclaration in yacc gives parsing erroryacc中多重和重新声明的简单语义分析器给出解析错误
【发布时间】:2020-11-29 14:32:04
【问题描述】:

这是我的一个简单语义分析器的代码,它只检查重新声明和多个声明。 这是 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;
[ \n\t] {;}
"+"  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 -> %s\n",temp);
                        }
                        else {
                                printf("Multiple Declaration of Variable\n");
                                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 %s\n", yytext);
        else{
                printf("\nParsing Error at line %d for string %s\n", 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("%s\n",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;

【问题讨论】:

    标签: c++ parsing yacc lex semantic-analysis


    【解决方案1】:

    您的 lex 文件中有两条规则:

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

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

    如果您交换这些行,您将看到与该模式匹配的事物的 ID 标记,而仅针对与 ID 规则不匹配的事物获得 alpha 标记。

    【讨论】:

    • 我明白你的意思。事实上,我应该删除 int 和 a 之间的空格,因为它不包含在规则中。在最新的编辑中,我在规则中加入了 Space 标记,我修改后的输入文件看起来像“int a,a,b,c;”。这次我遇到了分段错误。请参考编辑。提前致谢,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多