在flex&bison的基础上利用符号表进行语义分析
来源:互联网 发布:蓝牙小车单片机程序 编辑:程序博客网 时间:2024/05/16 13:46
如何编译
两种方法:
(1)使用make命令:先将要执行的所有命令写入到Makefile文件中,然后执行make命令,这就相当于将Makefile中的所有命令都执行完毕了,在终端可以清楚地看到系统每执行一条命令的结果,如果有错或者有警告都会输出。make执行完之后,就生成a.out文件,使用cat filename|./a.out就可以对filename中的文件就行语义分析了。
当文件有更新时,只需要执行以下make即可。
(2)这种是最笨的方法,就是不写Makefile文件,每次都是逐条去执行编译命令,文件有更新之后也要逐条执行,这种效率是最低的。make命令的出现就是为了提高编译效率的,有关make的知识点可以自行百度。
下面是第一种编译方法的具体过程:
0,Makefile——编译文件
程序总共包含4个文件gramtree_v1.h gramtree_v1.c gramtree.l gramtree_v1.y
gramtree_v1.h gramtree_v1.c定义和实现了创建语法树和遍历语法树的函数
gramtree.l是flex词法分析模块
gramtree_v1.y是bison语法分析模块
编译时使用Makefile文件,编写文件内容,vim Makefile
result:gramtree_v1.y gramtree.l gramtree_v1.h bison -d gramtree_v1.y flex gramtree.l gcc gramtree_v1.tab.c lex.yy.c gramtree_v1.c
编译过程如下:
[root@localhost flex]# make[root@localhost flex]# cat input3.c|./a.out
先执行make命令,这代表Makefile的编译步骤全都执行完毕了。然后使用
cat filename|./a.out就可以对filename中的代码进行语义分析。
/**Name:gramtree_v1.h*Author:WangLin*Created on:2015-10-03*Version 2.0*Function:定义语法树&变量符号表&函数符号表&数组符号表&结构体符号表*//*来自于词法分析器*/extern int yylineno;//行号extern char* yytext;//词void yyerror(char *s,...);//错误处理函数/*抽象语法树的结点*/struct ast{ int line; //行号 char* name;//语法单元的名字 int tag;//1为变量,2为函数,3为常数,4为数组,5为结构体 struct ast *l;//左孩子 struct ast *r;//右孩子 char* content;//语法单元语义值(int i;i是一个ID,ID的content是‘i’) char* type;//语法单元数据类型:主要用于等号和操作符左右类型匹配判断 float value;//常数值(记录integer和float的数据值)};/*变量符号表的结点*/struct var{ char* name;//变量名 char* type;//变量类型 struct var *next;//指针}*varhead,*vartail;/*函数符号表的结点*/struct func{ int tag;//0表示未定义,1表示定义 char* name;//函数名 char* type;//函数类型 char* rtype;//实际返回值类型 int pnum;//形参数个数 struct func *next;}*funchead,*functail;int rpnum;//记录函数实参个数/*数组符号表的结点*/struct array{ char* name;//数组名 char* type;//数组类型 struct array *next;}*arrayhead,*arraytail;/*结构体符号表的结点*/struct struc{ char* name;//结构体名 char* type;//数组类型 struct struc *next;}*struchead,*structail;/*=====抽象语法树========================*//*构造抽象语法树,变长参数,name:语法单元名字;num:变长参数中语法结点个数*/struct ast *newast(char* name,int num,...);/*遍历抽象语法树,level为树的层数*/void eval(struct ast*,int level);/*=====变量符号表========================*//*建立变量符号表*/void newvar(int num,...);/*查找变量是否已经定义,是返回1,否返回0*/int exitvar(struct ast*tp);/*查找变量类型*/char* typevar(struct ast*tp);/*=================函数符号表==============*//*建立函数符号表,flag:1表示变量符号表,2表示函数符号表,num是参数个数*/void newfunc(int num,...);/*查找函数是否已经定义,是返回1,否返回0*/int extitfunc(struct ast*tp);/*查找函数类型*/char* typefunc(struct ast*tp);/*查找函数的形参个数*/int pnumfunc(struct ast*tp);/*=================数组符号表==============*//*建立数组符号表*/void newarray(int num,...);/*查找数组是否已经定义,是返回1,否返回0*/int extitarray(struct ast*tp);/*查找数组类型*/char* typearray(struct ast*tp);/*=================结构体符号表==============*//*建立结构体符号表*/void newstruc(int num,...);/*查找结构体是否已经定义,是返回1,否返回0*/int extitstruc(struct ast*tp);
/**Name:gramtree_v1.c*Author:WangLin*Created on:2015-10-03*Function:实现变长参数构造树&遍历树函数&错误处理函数,yyparse()启动文法分析*/# include<stdio.h># include<stdlib.h># include<stdarg.h>//变长参数函数所需的头文件# include"gramtree_v1.h"int i;struct ast *newast(char* name,int num,...)//抽象语法树建立{ va_list valist; //定义变长参数列表 struct ast *a=(struct ast*)malloc(sizeof(struct ast));//新生成的父节点 struct ast *temp=(struct ast*)malloc(sizeof(struct ast)); if(!a) { yyerror("out of space"); exit(0); } a->name=name;//语法单元名字 va_start(valist,num);//初始化变长参数为num后的参数 if(num>0)//num>0为非终结符:变长参数均为语法树结点,孩子兄弟表示法 { temp=va_arg(valist, struct ast*);//取变长参数列表中的第一个结点设为a的左孩子 a->l=temp; a->line=temp->line;//父节点a的行号等于左孩子的行号 if(num==1)//只有一个孩子 { a->content=temp->content;//父节点的语义值等于左孩子的语义值 a->tag=temp->tag; } else //可以规约到a的语法单元>=2 { for(i=0; i<num-1; ++i)//取变长参数列表中的剩余结点,依次设置成兄弟结点 { temp->r=va_arg(valist,struct ast*); temp=temp->r; } } } else //num==0为终结符或产生空的语法单元:第1个变长参数表示行号,产生空的语法单元行号为-1。 { int t=va_arg(valist, int); //取第1个变长参数 a->line=t; if(!strcmp(a->name,"INTEGER"))//函数符号表头指针a->name,"INTEGER")) { a->type="int"; } else if(!strcmp(a->name,"FLOAT")) { a->type="float"; a->value=atof(yytext); } else { char* s; s=(char*)malloc(sizeof(char* )*40); strcpy(s,yytext);//存储词法单元的语义值 a->content=s; } } return a;}void eval(struct ast *a,int level)//先序遍历抽象语法树{ if(a!=NULL) { for(i=0; i<level; ++i)//孩子结点相对父节点缩进2个空格 printf(" "); if(a->line!=-1) //产生空的语法单元不需要打印信息 { printf("%s ",a->name);//打印语法单元名字,ID/TYPE/INTEGER要打印yytext的值 if((!strcmp(a->name,"ID"))||(!strcmp(a->name,"TYPE")))printf(":%s ",a->content); else if(!strcmp(a->name,"INTEGER"))printf(":%d",a->type); else printf("(%d)",a->line); } printf("\n"); eval(a->l,level+1);//遍历左子树 eval(a->r,level);//遍历右子树 }}/*====(1)变量符号表的建立和查询================*/void newvar(int num,...)//1)创建变量符号表{ va_list valist; //定义变长参数列表 struct var *a=(struct var*)malloc(sizeof(struct var));//新生成的父节点 struct ast *temp=(struct ast*)malloc(sizeof(struct ast)); va_start(valist,num);//初始化变长参数为num后的参数 temp=va_arg(valist, struct ast*);//取变长参数列表中的第一个结点 a->type=temp->content; temp=va_arg(valist, struct ast*);//取变长参数列表中的第二个结点 a->name=temp->content; vartail->next=a; vartail=a;}int exitvar(struct ast* tp)//2)查找变量是否已经定义,是返回1,否返回0{ struct var* p=(struct var*)malloc(sizeof(struct var*)); p=varhead->next; int flag=0; while(p!=NULL) { if(!strcmp(p->name,tp->content)) { flag=1; //存在返回1 return 1; } p=p->next; } if(!flag) { return 0;//不存在返回0 }}char* typevar(struct ast*tp)//3)查找变量类型{ struct var* p=(struct var*)malloc(sizeof(struct var*)); p=varhead->next; while(p!=NULL) { if(!strcmp(p->name,tp->content)) return p->type;//返回变量类型 p=p->next; }}/*====(2)函数符号表的建立和查询================*/void newfunc(int num,...)//1)创建函数符号表{ va_list valist; //定义变长参数列表 struct ast *temp=(struct ast*)malloc(sizeof(struct ast)); va_start(valist,num);//初始化变长参数为num后的参数 switch(num) { case 1: functail->pnum+=1;//参数个数加1 break; case 2://记录函数名 temp=va_arg(valist, struct ast*);//取变长参数列表中的第1个结点 functail->name=temp->content; break; case 3://记录实际返回值 temp=va_arg(valist, struct ast*);//取变长参数列表中的第1个结点 functail->rtype=temp->type; break; default://记录函数类型,返回类型不匹配则报出错误 rpnum=0;//将实参个数清0 temp=va_arg(valist, struct ast*);//取变长参数列表中的第1个结点 if(functail->rtype!=NULL)//实际返回类型和函数定义的返回类型比较 { if(strcmp(temp->content,functail->rtype))printf("Error type 8 at Line %d:Type mismatched for return.\n",yylineno); } functail->type=temp->type; functail->tag=1;//标志为已定义 struct func *a=(struct func*)malloc(sizeof(struct func)); functail->next=a;//尾指针指向下一个空结点 functail=a; break; }}int exitfunc(struct ast* tp)//2)查找函数是否已经定义,是返回1,否返回0{ int flag=0; struct func* p=(struct func*)malloc(sizeof(struct func*)); p=funchead->next; while(p!=NULL&&p->name!=NULL&&p->tag==1) { if(!strcmp(p->name,tp->content)) { flag=1; //存在返回1 return 1; } p=p->next; } if(!flag) return 0;//不存在返回0}char* typefunc(struct ast*tp)//3)查找函数类型{ struct func* p=(struct func*)malloc(sizeof(struct func*)); p=funchead->next; while(p!=NULL) { if(!strcmp(p->name,tp->content)) return p->type;//返回函数类型 p=p->next; }}int pnumfunc(struct ast*tp)//4)查找函数的形参个数{ struct func* p=(struct func*)malloc(sizeof(struct func*)); p=funchead->next; while(p!=NULL) { if(!strcmp(p->name,tp->content)) return p->pnum;//返回形参个数 p=p->next; }}/*====(3)数组符号表的建立和查询================*/void newarray(int num,...)//1)创建数组符号表{ va_list valist; //定义变长参数列表 struct array *a=(struct array*)malloc(sizeof(struct array));//新生成的父节点 struct ast *temp=(struct ast*)malloc(sizeof(struct ast)); va_start(valist,num);//初始化变长参数为num后的参数 temp=va_arg(valist, struct ast*);//取变长参数列表中的第一个结点 a->type=temp->content; temp=va_arg(valist, struct ast*);//取变长参数列表中的第二个结点 a->name=temp->content; arraytail->next=a; arraytail=a;}int exitarray(struct ast* tp)//2)查找数组是否已经定义,是返回1,否返回0{ struct array* p=(struct array*)malloc(sizeof(struct array*)); p=arrayhead->next; int flag=0; while(p!=NULL) { if(!strcmp(p->name,tp->content)) { flag=1; //存在返回1 return 1; } p=p->next; } if(!flag) { return 0;//不存在返回0 }}char* typearray(struct ast* tp)//3)查找数组类型{ struct array* p=(struct array*)malloc(sizeof(struct array*)); p=arrayhead->next; while(p!=NULL) { if(!strcmp(p->name,tp->content)) return p->type;//返回数组类型 p=p->next; }}/*====(4)结构体符号表的建立和查询================*/void newstruc(int num,...)//1)创建结构体符号表{ va_list valist; //定义变长参数列表 struct struc *a=(struct struc*)malloc(sizeof(struct struc));//新生成的父节点 struct ast *temp=(struct ast*)malloc(sizeof(struct ast)); va_start(valist,num);//初始化变长参数为num后的参数 temp=va_arg(valist, struct ast*);//取变长参数列表中的第二个结点 a->name=temp->content; structail->next=a; structail=a;}int exitstruc(struct ast* tp)//2)查找结构体是否已经定义,是返回1,否返回0{ struct struc* p=(struct struc*)malloc(sizeof(struct struc*)); p=struchead->next; int flag=0; while(p!=NULL) { if(!strcmp(p->name,tp->content)) { flag=1; //存在返回1 return 1; } p=p->next; } if(!flag) { return 0;//不存在返回0 }}void yyerror(char*s,...) //变长参数错误处理函数{ va_list ap; va_start(ap,s); fprintf(stderr,"%d:error:",yylineno);//错误行号 vfprintf(stderr,s,ap); fprintf(stderr,"\n");}int main(){ varhead=(struct var*)malloc(sizeof(struct var));//变量符号表头指针 vartail=varhead;//变量符号表尾指针 funchead=(struct func*)malloc(sizeof(struct func));//函数符号表头指针 functail=(struct func*)malloc(sizeof(struct func));//函数符号表头指针 funchead->next=functail;//函数符号表尾指针 functail->pnum=0; arrayhead=(struct array*)malloc(sizeof(struct array));//数组符号表头指针 arraytail=arrayhead; struchead=(struct struc*)malloc(sizeof(struct struc));//结构体符号表头指针 structail=struchead;//结构体符号表尾指针 return yyparse(); //启动文法分析,调用词法分析}
/**Name:gramtree.l*Author:WangLin*Created on:2015-10-03*Function:词法分析模块,对每个终结符建立一个叶子结点,返回记号,供bison语法分析使用*/%{#include "stdio.h"#include "stdlib.h"# include "gramtree_v1.h"#include "gramtree_v1.tab.h"%}%option yylinenoTYPE int|floatSTRUCT structRETURN returnIF ifELSE elseWHILE whilePLUS \+MINUS -INTEGER [1-9]+[0-9]*|0 FLOAT [0-9]+\.[0-9]* ID [a-z_A-Z][a-zA-Z_0-9]*SPACE [ \t\r]*EOL \nSEMI ;COMMA ,ASSIGNOP =RELOP >|<|>=|<=|==|!=STAR \*DIV \/AND &&OR \|\|DOT \.NOT !LP \(RP \)LB \[RB \]LC \{RC \}AERROR .%%int|float {yylval.a=newast("TYPE",0,yylineno);return TYPE;}struct {yylval.a=newast("STRUCT",0,yylineno);return STRUCT;}{RETURN} {yylval.a=newast("RETURN",0,yylineno); return RETURN;}{IF} { yylval.a=newast("IF",0,yylineno);return IF;}{ELSE} {yylval.a=newast("ELSE",0,yylineno); return ELSE;}{WHILE} {yylval.a=newast("WHILE",0,yylineno); return WHILE;}{PLUS} {yylval.a=newast("PLUS",0,yylineno); return PLUS;}{MINUS} {yylval.a=newast("MINUS",0,yylineno); return MINUS;}{INTEGER} {yylval.a=newast("INTEGER",0,yylineno); return INTEGER;}{ID} {yylval.a=newast("ID",0,yylineno); return ID;}{SPACE} {}{EOL} {}{SEMI} {yylval.a=newast("SEMI",0,yylineno); return SEMI;}{COMMA} {yylval.a=newast("COMMA",0,yylineno); return COMMA;}{ASSIGNOP} {yylval.a=newast("ASSIGNOP",0,yylineno); return ASSIGNOP;}{RELOP} {yylval.a=newast("RELOP",0,yylineno); return RELOP;}{STAR} {yylval.a=newast("STAR",0,yylineno); return STAR;}{DIV} {yylval.a=newast("DIV",0,yylineno); return DIV;}{AND} {yylval.a=newast("AND",0,yylineno); return AND;}{OR} {yylval.a=newast("OR",0,yylineno); return OR;}{DOT} {yylval.a=newast("DOT",0,yylineno); return DOT;}{NOT} {yylval.a=newast("NOT",0,yylineno); return NOT;}{LP} {yylval.a=newast("LP",0,yylineno); return LP;}{RP} {yylval.a=newast("RP",0,yylineno); return RP;}{LB} {yylval.a=newast("LB",0,yylineno); return LB;}{RB} {yylval.a=newast("RB",0,yylineno); return RB;}{LC} {yylval.a=newast("LC",0,yylineno); return LC;}{RC} {yylval.a=newast("RC",0,yylineno); return RC;}{AERROR} { printf("Error type A at line %d: Mystirious charachter '%s'\n",yylineno,yytext);}%%int yywrap(){ return 1;}
/**Name:gramtree_v1.y*Author:WangLin*Created on:2015-10-03*Version 2.0*Function:bison语法分析&语义分析*/%{#include<unistd.h>#include<stdio.h>#include "gramtree_v1.h"//语法树&符号表创建和查询函数%}%union{struct ast* a;double d;}/*declare tokens*/%token <a> INTEGER FLOAT%token <a> TYPE STRUCT RETURN IF ELSE WHILE ID SPACE SEMI COMMA ASSIGNOP RELOP PLUSMINUS STAR DIV AND OR DOT NOT LP RP LB RB LC RC AERROR%token <a> EOL%type <a> Program ExtDefList ExtDef ExtDecList Specifire StructSpecifireOptTag Tag VarDec FunDec VarList ParamDec Compst StmtList Stmt DefList Def DecList Dec Exp Args/*priority*/%right ASSIGNOP%left OR%left AND%left RELOP%left PLUS MINUS%left STAR DIV%right NOT%left LP RP LB RB DOT%%Program:ExtDefList {$$=newast("Program",1,$1);} ;ExtDefList:ExtDef ExtDefList {$$=newast("ExtDefList",2,$1,$2);} | {$$=newast("ExtDefList",0,-1);} ;ExtDef:Specifire ExtDecList SEMI //变量定义:检查是否重定义Error type 3 { $$=newast("ExtDef",3,$1,$2,$3); if(exitvar($2)) printf("Error type 3 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content); else newvar(2,$1,$2); } |Specifire SEMI {$$=newast("ExtDef",2,$1,$2);} |Specifire FunDec Compst //函数定义:检查实际返回类型与函数类型是否匹配Error type 8 { $$=newast("ExtDef",3,$1,$2,$3); newfunc(4,$1); } ;ExtDecList:VarDec {$$=newast("ExtDecList",1,$1);} |VarDec COMMA ExtDecList {$$=newast("ExtDecList",3,$1,$2,$3);} ;/*Specifire*/Specifire:TYPE {$$=newast("Specifire",1,$1);} |StructSpecifire {$$=newast("Specifire",1,$1);} ;StructSpecifire:STRUCT OptTag LC DefList RC //结构体定义:检查是否重定义Error type 16 { $$=newast("StructSpecifire",5,$1,$2,$3,$4,$5); if(exitstruc($2))printf("Error type 16 at Line %d:Duplicated name '%s'\n",yylineno,$2->content); else newstruc(1,$2); } |STRUCT Tag //结构体引用:检查是否未定义就引用Error type 17{ $$=newast("StructSpecifire",2,$1,$2); if(!exitstruc($2)) printf("Error type 17 at Line %d:undefined structure '%s'\n",yylineno,$2->content); } ;OptTag:ID {$$=newast("OptTag",1,$1);} |{$$=newast("OptTag",0,-1);} ;Tag:ID {$$=newast("Tag",1,$1);} ;/*Declarators*/VarDec:ID {$$=newast("VarDec",1,$1);$$->tag=1;} | VarDec LB INTEGER RB {$$=newast("VarDec",4,$1,$2,$3,$4);$$->content=$1->content;$$->tag=4;} ;FunDec:ID LP VarList RP //函数定义:检查是否重复定义Error type 4 {$$=newast("FunDec",4,$1,$2,$3,$4);$$->content=$1->content; if(exitfunc($1)) printf("Error type 4 at Line %d:Redefined Function '%s'\n",yylineno,$1->content); else newfunc(2,$1);} |ID LP RP //函数定义:检查是否重复定义Error type 4 {$$=newast("FunDec",3,$1,$2,$3);$$->content=$1->content; if(exitfunc($1)) printf("Error type 4 at Line %d:Redefined Function '%s'\n",yylineno,$1->content); else newfunc(2,$1);} ;VarList:ParamDec COMMA VarList {$$=newast("VarList",3,$1,$2,$3);} |ParamDec {$$=newast("VarList",1,$1);} ;ParamDec:Specifire VarDec {$$=newast("ParamDec",2,$1,$2);newvar(2,$1,$2);newfunc(1);} ;/*Statement*/Compst:LC DefList StmtList RC {$$=newast("Compst",4,$1,$2,$3,$4);} ;StmtList:Stmt StmtList{$$=newast("StmtList",2,$1,$2);} | {$$=newast("StmtList",0,-1);} ;Stmt:Exp SEMI {$$=newast("Stmt",2,$1,$2);} |Compst {$$=newast("Stmt",1,$1);} |RETURN Exp SEMI {$$=newast("Stmt",3,$1,$2,$3); |IF LP Exp RP Stmt ELSE Stmt {$$=newast("Stmt",7,$1,$2,$3,$4,$5,$6,$7);} |WHILE LP Exp RP Stmt {$$=newast("Stmt",5,$1,$2,$3,$4,$5);} ;/*Local Definitions*/DefList:Def DefList{$$=newast("DefList",2,$1,$2);} | {$$=newast("DefList",0,-1);} ;Def:Specifire DecList SEMI //变量或数组定义:检查变量是否重定义 Error type 3{$$=newast("Def",3,$1,$2,$3); if(exitvar($2)||exitarray($2)) printf("Error type 3 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content); else if($2->tag==4) newarray(2,$1,$2); else newvar(2,$1,$2);} ;DecList:Dec {$$=newast("DecList",1,$1);} |Dec COMMA DecList {$$=newast("DecList",3,$1,$2,$3);$$->tag=$3->tag;} ;Dec:VarDec {$$=newast("Dec",1,$1);} |VarDec ASSIGNOP Exp {$$=newast("Dec",3,$1,$2,$3);$$->content=$1->content;} ;/*Expressions*/Exp:Exp ASSIGNOP Exp{$$=newast("Exp",3,$1,$2,$3);//检查等号左右类型匹配判断Error type 5 if(strcmp($1->type,$3->type)){printf("Error type 5 at Line %d:Type mismatched for assignment.\n ",yylineno);} |Exp AND Exp{$$=newast("Exp",3,$1,$2,$3);} |Exp PLUS Exp{$$=newast("Exp",3,$1,$2,$3);//检查操作符左右类型Error type 7 if(strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}} |Exp STAR Exp{$$=newast("Exp",3,$1,$2,$3);//检查操作符左右类型Error type 7 if(strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}} |Exp DIV Exp{$$=newast("Exp",3,$1,$2,$3);//检查操作符左右类型Error type 7 if(strcmp($1->type,$3->type)){printf("Error type 7 at Line %d:Type mismatched for operand.\n ",yylineno);}} |LP Exp RP{$$=newast("Exp",3,$1,$2,$3);} |MINUS Exp {$$=newast("Exp",2,$1,$2);} |NOT Exp {$$=newast("Exp",2,$1,$2);} |ID LP Args RP {$$=newast("Exp",4,$1,$2,$3,$4);//函数引用:检查是否未定义就调用Error type 2 else if(!exitfunc($1)){printf("Error type 2 at Line %d:undefined Function %s\n ",yylineno,$1->content);} |ID LP RP {$$=newast("Exp",3,$1,$2,$3);} |Exp LB Exp RB //数组引用:是否定义&标识误用&下标 Error type 10,Error type 12 {$$=newast("Exp",4,$1,$2,$3,$4); if(strcmp($3->type,"int"))printf("Error type 12 at Line %d:%.1f is not a integer.\n",yylineno,$3->value); if((!exitarray($1))&&(exitvar($1)||exitfunc($1)))printf("Error type 10 at Line %d:'%s'is not an array.\n ",yylineno,$1->content); else if(!exitarray($1)){printf("Error type 2 at Line %d:undefined Array %s\n ",yylineno,$1->content);}} |Exp DOT ID //结构体引用:检查点号引用Error type 13 {$$=newast("Exp",3,$1,$2,$3);if(!exitstruc($1))printf("Error type 13 at Line %d:Illegal use of '.'.\n",yylineno);} |ID //变量引用:检查是否定义Error type 1 { $$=newast("Exp",1,$1); if(!exitvar($1)&&!exitarray($1)) printf("Error type 1 at Line %d:undefined variable %s\n ",yylineno,$1->content); else $$->type=typevar($1); } |INTEGER {$$=newast("Exp",1,$1);$$->tag=3;$$->type="int";} //整型常数 |FLOAT{$$=newast("Exp",1,$1);$$->tag=3;$$->type="float";$$->value=$1->value;} //浮点型常数 ;Args:Exp COMMA Args {$$=newast("Args",3,$1,$2,$3);rpnum+=1;} //记录形参个数 |Exp {$$=newast("Args",1,$1);rpnum+=1;} //记录形参个数 ;%%
实验结果
test1.c 变量在使用时未经定义。
test2.c 函数在调用时未经定义。
test3.c 变量重复定义
test4.c 函数重复定义
test5.c 赋值号左右两边的表达式类型不匹配
test6.c 赋值号左边出现一个只有右值的表达式
test7.c 操作数类型不匹配
test8.c return语句的返回类型与函数定义的返回类型不匹配
test9.c 函数调用时实参与形参的数目不匹配
test10.c 对非数组类型使用了[]数组访问的操作符
test11.c 对普通变量使用了函数调用的操作符
test12.c 数组访问下标出现了非整数
test13.c 对非结构体变量使用了.操作符
test15. 结构体域重复定义
test16.c 结构体名字重复定义
test17.c 结构体在调用时未经定义
[root@localhost flex]# cat test1.c int main(){int i=0;j=i+1;}
[root@localhost flex]# cat test1.c|./a.out Error type 1 at Line 4:undefined variable j
[root@localhost flex]# cat test2.c int main(){int i=0;inc(i);}
[root@localhost flex]# cat test2.c|./a.out Error type 2 at Line 4:undefined Function inc
[root@localhost flex]# cat test3.c int main(){int i;float i;int j;float j;}
[root@localhost flex]# cat test3.c|./a.out Error type 3 at Line 4:Redefined Variable 'i'Error type 3 at Line 6:Redefined Variable 'j'
[root@localhost flex]# cat test4.c int func(int i){ return i;}int func(){ return 0;}int main(){}
[root@localhost flex]# cat test4.c|./a.out Error type 4 at Line 5:Redefined Function 'func'
[root@localhost flex]# cat test5.c int main(){ int i; i=3.7;}
[root@localhost flex]# cat test5.c|./a.out Error type 5 at Line 4:Type mismatched for assignment.
[root@localhost flex]# cat test6.c int main(){ int i; 10=i;}
[root@localhost flex]# cat test6.c|./a.out Error type 6 at Line 4:the left-hand side of an assignment must be a variable.
[root@localhost flex]# cat test7.c int main(){ float j; 10+j;}
[root@localhost flex]# cat test7.c|./a.out Error type 7 at Line 4:Type mismatched for operand.
[root@localhost flex]# cat test8.c int main(){ float j=1.7; return j;}
[root@localhost flex]# cat test8.c|./a.out Error type 8 at Line 5:Type mismatched for return.
[root@localhost flex]# cat test9.c int func(int i){ return i;}int main(){ func(1,2);}
[root@localhost flex]# cat test9.c|./a.out Error type 9 at Line 7:parameters num mismatched for function: func
[root@localhost flex]# cat test10.c int main(){ int i; i[0];}
[root@localhost flex]# cat test10.c|./a.out Error type 10 at Line 4:'i'is not an array.
[root@localhost flex]# cat test11.c int main(){ int i; i(10);}
[root@localhost flex]# cat test11.c|./a.out Error type 11 at Line 4:'i'is not a function.
[root@localhost flex]# cat test12.c int main(){ int i[10]; i[1.5]=10;}
[root@localhost flex]# cat test12.c|./a.out Error type 12 at Line 4:1.5 is not a integer.
[root@localhost flex]# cat test13.c struct Position{ float x; float y; };int main(){ int i; i.x;}
[root@localhost flex]# cat test13.c|./a.out Error type 13 at Line 9:Illegal use of '.'.
[root@localhost flex]# cat test15.c struct Position{ float x; float y; int x;};int main(){}
[root@localhost flex]# cat test15.c|./a.out Error type 3 at Line 5:Redefined Variable 'x'
[root@localhost flex]# cat test16.c struct Position{ float x; };struct Position{ float y; };int main(){}
[root@localhost flex]# cat test16.c|./a.out Error type 16 at Line 8:Duplicated name 'Position'
[root@localhost flex]# cat test17.c int main(){ struct Position pos;}
[root@localhost flex]# cat test17.c|./a.out Error type 17 at Line 3:undefined structure 'Position'
- 在flex&bison的基础上利用符号表进行语义分析
- Flex&Bison Tips - 如何改善 flex & bison 在VC下的编辑环境
- 利用flex & bison (lex & yacc)创建可重入(线程安全)的词法分析和语法解析器
- Flex&Bison Tips(2010-08-26)如何改善 flex & bison 在VC下的编辑环境
- Flex&Bison Tips(2010-08-27) 如何在VC中更好的断点调试flex&bison词法和语法分析器
- Flex和Bison进行语法分析(转载)
- bison和flex的基本原理
- bison和flex的例子
- flex 和 bison 的计算机
- Bison和Flex的学习
- flex、bison代码在visual studio 编译
- 在windows下安装flex和bison
- flex bison
- bison & flex
- flex&bison
- flex bison
- flex&&bison
- mongodb在副本集的基础上进行分片存储·
- 汇编实现两位数相加
- 什么叫长大?
- Codeforces 285E - Positions in Permutations 【题解待补全】
- 【Leetcode】N-Queens
- 前端5
- 在flex&bison的基础上利用符号表进行语义分析
- [ecshop 资料]商品显示 选择属性名称然后标题也加上属性的名称
- I2C总线简介
- UML学习:机房收费系统-对象图
- 第一部分、十道海量数据处理面试题
- Android 屏幕水平、垂直使用不同的布局xml文件
- kaldi学习笔记之卷积神经网络(CNN)
- 简单登入模块
- 非主流自然语言处理——遗忘算法系列(三):分词