如何編譯
兩種方法:
(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();
}
a->name=name;//文法單元名字
va_start(valist,num);//初始化變長參數為num後的參數
if(num>)//num>0為非終結符:變長參數均為文法樹結點,孩子兄弟表示法
{
temp=va_arg(valist, struct ast*);//取變長參數清單中的第一個結點設為a的左孩子
a->l=temp;
a->line=temp->line;//父節點a的行号等于左孩子的行号
if(num==)//隻有一個孩子
{
a->content=temp->content;//父節點的語義值等于左孩子的語義值
a->tag=temp->tag;
}
else //可以規約到a的文法單元>=2
{
for(i=; i<num-; ++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* )*);
strcpy(s,yytext);//存儲詞法單元的語義值
a->content=s;
}
}
return a;
}
void eval(struct ast *a,int level)//先序周遊抽象文法樹
{
if(a!=NULL)
{
for(i=; i<level; ++i)//孩子結點相對父節點縮進2個空格
printf(" ");
if(a->line!=-) //産生空的文法單元不需要列印資訊
{
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+);//周遊左子樹
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=;
while(p!=NULL)
{
if(!strcmp(p->name,tp->content))
{
flag=; //存在傳回1
return ;
}
p=p->next;
}
if(!flag)
{
return ;//不存在傳回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 :
functail->pnum+=;//參數個數加1
break;
case ://記錄函數名
temp=va_arg(valist, struct ast*);//取變長參數清單中的第1個結點
functail->name=temp->content;
break;
case ://記錄實際傳回值
temp=va_arg(valist, struct ast*);//取變長參數清單中的第1個結點
functail->rtype=temp->type;
break;
default://記錄函數類型,傳回類型不比對則報出錯誤
rpnum=;//将實參個數清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=;//标志為已定義
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=;
struct func* p=(struct func*)malloc(sizeof(struct func*));
p=funchead->next;
while(p!=NULL&&p->name!=NULL&&p->tag==)
{
if(!strcmp(p->name,tp->content))
{
flag=; //存在傳回1
return ;
}
p=p->next;
}
if(!flag)
return ;//不存在傳回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=;
while(p!=NULL)
{
if(!strcmp(p->name,tp->content))
{
flag=; //存在傳回1
return ;
}
p=p->next;
}
if(!flag)
{
return ;//不存在傳回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=;
while(p!=NULL)
{
if(!strcmp(p->name,tp->content))
{
flag=; //存在傳回1
return ;
}
p=p->next;
}
if(!flag)
{
return ;//不存在傳回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=;
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:--
*Function:詞法分析子產品,對每個終結符建立一個葉子結點,傳回記号,供bison文法分析使用
*/
%{
#include "stdio.h"
#include "stdlib.h"
# include "gramtree_v1.h"
#include "gramtree_v1.tab.h"
%}
%option yylineno
TYPE int|float
STRUCT struct
RETURN return
IF if
ELSE else
WHILE while
PLUS \+
MINUS -
INTEGER [-]+[-]*|
FLOAT [-]+\.[-]*
ID [a-z_A-Z][a-zA-Z_0-]*
SPACE [ \t\r]*
EOL \n
SEMI ;
COMMA ,
ASSIGNOP =
RELOP >|<|>=|<=|==|!=
STAR \*
DIV \/
AND &&
OR \|\|
DOT \.
NOT !
LP \(
RP \)
LB \[
RB \]
LC \{
RC \}
AERROR .
%%
int|float {yylval.a=newast("TYPE",,yylineno);return TYPE;}
struct {yylval.a=newast("STRUCT",,yylineno);return STRUCT;}
{RETURN} {yylval.a=newast("RETURN",,yylineno); return RETURN;}
{IF} { yylval.a=newast("IF",,yylineno);return IF;}
{ELSE} {yylval.a=newast("ELSE",,yylineno); return ELSE;}
{WHILE} {yylval.a=newast("WHILE",,yylineno); return WHILE;}
{PLUS} {yylval.a=newast("PLUS",,yylineno); return PLUS;}
{MINUS} {yylval.a=newast("MINUS",,yylineno); return MINUS;}
{INTEGER} {yylval.a=newast("INTEGER",,yylineno); return INTEGER;}
{ID} {yylval.a=newast("ID",,yylineno); return ID;}
{SPACE} {}
{EOL} {}
{SEMI} {yylval.a=newast("SEMI",,yylineno); return SEMI;}
{COMMA} {yylval.a=newast("COMMA",,yylineno); return COMMA;}
{ASSIGNOP} {yylval.a=newast("ASSIGNOP",,yylineno); return ASSIGNOP;}
{RELOP} {yylval.a=newast("RELOP",,yylineno); return RELOP;}
{STAR} {yylval.a=newast("STAR",,yylineno); return STAR;}
{DIV} {yylval.a=newast("DIV",,yylineno); return DIV;}
{AND} {yylval.a=newast("AND",,yylineno); return AND;}
{OR} {yylval.a=newast("OR",,yylineno); return OR;}
{DOT} {yylval.a=newast("DOT",,yylineno); return DOT;}
{NOT} {yylval.a=newast("NOT",,yylineno); return NOT;}
{LP} {yylval.a=newast("LP",,yylineno); return LP;}
{RP} {yylval.a=newast("RP",,yylineno); return RP;}
{LB} {yylval.a=newast("LB",,yylineno); return LB;}
{RB} {yylval.a=newast("RB",,yylineno); return RB;}
{LC} {yylval.a=newast("LC",,yylineno); return LC;}
{RC} {yylval.a=newast("RC",,yylineno); return RC;}
{AERROR} { printf("Error type A at line %d: Mystirious charachter '%s'\n",yylineno,yytext);}
%%
int yywrap()
{
return ;
}
/*
*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 PLUS
MINUS STAR DIV AND OR DOT NOT LP RP LB RB LC RC AERROR
%token <a> EOL
%type <a> Program ExtDefList ExtDef ExtDecList Specifire StructSpecifire
OptTag 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);}
;
ExtDefList:ExtDef ExtDefList {$$=newast("ExtDefList",,$1,$2);}
| {$$=newast("ExtDefList",,-);}
;
ExtDef:Specifire ExtDecList SEMI //變量定義:檢查是否重定義Error type 3
{
$$=newast("ExtDef",,$1,$2,$3);
if(exitvar($2)) printf("Error type 3 at Line %d:Redefined Variable '%s'\n",yylineno,$2->content);
else newvar(,$1,$2);
}
|Specifire SEMI {$$=newast("ExtDef",,$1,$2);}
|Specifire FunDec Compst //函數定義:檢查實際傳回類型與函數類型是否比對Error type 8
{
$$=newast("ExtDef",,$1,$2,$3);
newfunc(,$1);
}
;
ExtDecList:VarDec {$$=newast("ExtDecList",,$1);}
|VarDec COMMA ExtDecList {$$=newast("ExtDecList",,$1,$2,$3);}
;
/*Specifire*/
Specifire:TYPE {$$=newast("Specifire",,$1);}
|StructSpecifire {$$=newast("Specifire",,$1);}
;
StructSpecifire:STRUCT OptTag LC DefList RC //結構體定義:檢查是否重定義Error type 16
{
$$=newast("StructSpecifire",,$1,$2,$3,$4,$5);
if(exitstruc($2)) printf("Error type 16 at Line %d:Duplicated name '%s'\n",yylineno,$2->content);
else newstruc(,$2);
}
|STRUCT Tag //結構體引用:檢查是否未定義就引用Error type 17
{
$$=newast("StructSpecifire",,$1,$2);
if(!exitstruc($2)) printf("Error type 17 at Line %d:undefined structure '%s'\n",yylineno,$2->content);
}
;
OptTag:ID {$$=newast("OptTag",,$1);}
|{$$=newast("OptTag",,-);}
;
Tag:ID {$$=newast("Tag",,$1);}
;
/*Declarators*/
VarDec:ID {$$=newast("VarDec",,$1);$$->tag=;}
| VarDec LB INTEGER RB {$$=newast("VarDec",,$1,$2,$3,$4);$$->content=$1->content;$$->tag=;}
;
FunDec:ID LP VarList RP //函數定義:檢查是否重複定義Error type 4
{
$$=newast("FunDec",,$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(,$1);
}
|ID LP RP //函數定義:檢查是否重複定義Error type 4
{
$$=newast("FunDec",,$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(,$1);}
;
VarList:ParamDec COMMA VarList {$$=newast("VarList",,$1,$2,$3);}
|ParamDec {$$=newast("VarList",,$1);}
;
ParamDec:Specifire VarDec {$$=newast("ParamDec",,$1,$2);newvar(,$1,$2);newfunc();}
;
/*Statement*/
Compst:LC DefList StmtList RC {$$=newast("Compst",,$1,$2,$3,$4);}
;
StmtList:Stmt StmtList{$$=newast("StmtList",,$1,$2);}
| {$$=newast("StmtList",,-);}
;
Stmt:Exp SEMI {$$=newast("Stmt",,$1,$2);}
|Compst {$$=newast("Stmt",,$1);}
|RETURN Exp SEMI {$$=newast("Stmt",,$1,$2,$3);
|IF LP Exp RP Stmt ELSE Stmt {$$=newast("Stmt",,$1,$2,$3,$4,$5,$6,$7);}
|WHILE LP Exp RP Stmt {$$=newast("Stmt",,$1,$2,$3,$4,$5);}
;
/*Local Definitions*/
DefList:Def DefList{$$=newast("DefList",,$1,$2);}
| {$$=newast("DefList",,-);}
;
Def:Specifire DecList SEMI //變量或數組定義:檢查變量是否重定義 Error type 3
{
$$=newast("Def",,$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==) newarray(,$1,$2);
else newvar(,$1,$2);
}
;
DecList:Dec {$$=newast("DecList",,$1);}
|Dec COMMA DecList {$$=newast("DecList",,$1,$2,$3);$$->tag=$3->tag;}
;
Dec:VarDec {$$=newast("Dec",,$1);}
|VarDec ASSIGNOP Exp {$$=newast("Dec",,$1,$2,$3);$$->content=$1->content;}
;
/*Expressions*/
Exp:Exp ASSIGNOP Exp{$$=newast("Exp",,$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",,$1,$2,$3);}
|Exp PLUS Exp{$$=newast("Exp",,$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",,$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",,$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",,$1,$2,$3);}
|MINUS Exp {$$=newast("Exp",,$1,$2);}
|NOT Exp {$$=newast("Exp",,$1,$2);}
|ID LP Args RP {$$=newast("Exp",,$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",,$1,$2,$3);}
|Exp LB Exp RB //數組引用:是否定義&辨別誤用&下标 Error type 10,Error type 12
{$$=newast("Exp",,$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",,$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);
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);$$->tag=;$$->type="int";} //整型常數
|FLOAT{$$=newast("Exp",,$1);$$->tag=;$$->type="float";$$->value=$1->value;} //浮點型常數
;
Args:Exp COMMA Args {$$=newast("Args",,$1,$2,$3);rpnum+=;} //記錄形參個數
|Exp {$$=newast("Args",,$1);rpnum+=;} //記錄形參個數
;
%%
實驗結果
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=;
j=i+;
}
[root@localhost flex]# cat test1.c|./a.out
Error type at Line :undefined variable j
[root@localhost flex]# cat test2.c
int main()
{
int i=;
inc(i);
}
[root@localhost flex]# cat test2.c|./a.out
Error type at Line :undefined Function inc
[[email protected] flex]# cat test3.c
int main()
{
int i;
float i;
int j;
float j;
}
[[email protected] flex]# cat test3.c|./a.out
Error type at Line :Redefined Variable 'i'
Error type at Line :Redefined Variable 'j'
[root@localhost flex]# cat test4.c
int func(int i)
{
return i;
}
int func()
{
return ;
}
int main()
{
}
[root@localhost flex]# cat test4.c|./a.out
Error type at Line :Redefined Function 'func'
[root@localhost flex]# cat test5.c
int main()
{
int i;
i=;
}
[root@localhost flex]# cat test5.c|./a.out
Error type at Line :Type mismatched for assignment.
[root@localhost flex]# cat test6.c
int main()
{
int i;
=i;
}
[[email protected] flex]# cat test6.c|./a.out
Error type at Line :the left-hand side of an assignment must be a variable.
[[email protected] flex]# cat test7.c
int main()
{
float j;
+j;
}
[root@localhost flex]# cat test7.c|./a.out
Error type at Line :Type mismatched for operand.
[[email protected] flex]# cat test8.c
int main()
{
float j=;
return j;
}
[root@localhost flex]# cat test8.c|./a.out
Error type at Line :Type mismatched for return.
[root@localhost flex]# cat test9.c
int func(int i)
{
return i;
}
int main()
{
func(,);
}
[[email protected] flex]# cat test9.c|./a.out
Error type at Line :parameters num mismatched for function: func
[root@localhost flex]# cat test10.c
int main()
{
int i;
i[];
}
[[email protected] flex]# cat test10.c|./a.out
Error type at Line :'i'is not an array.
[root@localhost flex]# cat test11.c
int main()
{
int i;
i();
}
[[email protected] flex]# cat test11.c|./a.out
Error type at Line :'i'is not a function.
[root@localhost flex]# cat test12.c
int main()
{
int i[];
i[]=;
}
[[email protected] flex]# cat test12.c|./a.out
Error type at Line : is not a integer.
[[email protected] 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 at Line :Illegal use of '.'.
[[email protected] flex]# cat test15.c
struct Position
{
float x;
float y;
int x;
};
int main()
{
}
[root@localhost flex]# cat test15.c|./a.out
Error type at Line :Redefined Variable 'x'
[[email protected] flex]# cat test16.c
struct Position
{
float x;
};
struct Position
{
float y;
};
int main()
{
}
[root@localhost flex]# cat test16.c|./a.out
Error type at Line :Duplicated name 'Position'
[root@localhost flex]# cat test17.c
int main()
{
struct Position pos;
}
[root@localhost flex]# cat test17.c|./a.out
Error type at Line :undefined structure 'Position'