当前位置:   article > 正文

在flex&bison的基础上利用符号表进行语义分析_flex bison 符号表

flex bison 符号表

如何编译

两种方法:
(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 
  • 1
  • 2
  • 3
  • 4
  • 5

编译过程如下:

[root@localhost flex]# make
[root@localhost flex]# cat input3.c|./a.out 
  • 1
  • 2
  • 3

先执行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);


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
/*
*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(); //启动文法分析,调用词法分析
}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
/*
*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 yylineno
TYPE int|float
STRUCT struct
RETURN return
IF if
ELSE else
WHILE while
PLUS \+
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 \n
SEMI ;
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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
/*
*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,$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;} //记录形参个数
        ;
%%

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181

实验结果

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test1.c|./a.out 
Error type 1 at Line 4:undefined variable j
  • 1
  • 2
[root@localhost flex]# cat test2.c 
int main()
{
int i=0;
inc(i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test2.c|./a.out 
Error type 2 at Line 4:undefined Function inc
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test3.c 
int main()
{
int i;
float i;
int j;
float j;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
[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'
  • 1
  • 2
  • 3
  • 4
[root@localhost flex]# cat test4.c 
int func(int i)
{
    return i;
}
int func()
{
    return 0;
}
int main()
{

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
[root@localhost flex]# cat test4.c|./a.out 
Error type 4 at Line 5:Redefined Function 'func'
  • 1
  • 2
[root@localhost flex]# cat test5.c 
int main()
{
    int i;
    i=3.7;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test5.c|./a.out 
Error type 5 at Line 4:Type mismatched for assignment.
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test6.c 
int main()
{
    int i;
    10=i;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[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.
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test7.c 
int main()
{
    float j;
    10+j;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test7.c|./a.out 
Error type 7 at Line 4:Type mismatched for operand.
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test8.c 
int main()
{
    float j=1.7;
    return j;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test8.c|./a.out 
Error type 8 at Line 5:Type mismatched for return.
  • 1
  • 2
[root@localhost flex]# cat test9.c 
int func(int i)
{
    return i;
}
int main()
{
    func(1,2);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
[root@localhost flex]# cat test9.c|./a.out 
Error type 9 at Line 7:parameters num mismatched for function: func
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test10.c 
int main()
{
    int i;
    i[0];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
 [root@localhost flex]# cat test10.c|./a.out 
Error type 10 at Line 4:'i'is not an array.
  • 1
  • 2
  • 3
[root@localhost flex]# cat test11.c 
int main()
{
    int i;
    i(10);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test11.c|./a.out 
Error type 11 at Line 4:'i'is not a function.
  • 1
  • 2
  • 3
 [root@localhost flex]# cat test12.c 
int main()
{
    int i[10];
    i[1.5]=10;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test12.c|./a.out 
Error type 12 at Line 4:1.5 is not a integer.
  • 1
  • 2
  • 3
[root@localhost flex]# cat test13.c 
struct Position
{
  float x;
  float y;  
};
int main()
{
    int i;
    i.x;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
[root@localhost flex]# cat test13.c|./a.out 
Error type 13 at Line 9:Illegal use of '.'.
  • 1
  • 2
  • 3
[root@localhost flex]# cat test15.c 
struct Position
{
  float x;
  float y;  
  int x;
};
int main()
{
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
[root@localhost flex]# cat test15.c|./a.out 
Error type 3 at Line 5:Redefined Variable 'x'
  • 1
  • 2
  • 3
[root@localhost flex]# cat test16.c 
struct Position
{
  float x;  
};
struct Position
{
  float y;  
};

int main()
{
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
[root@localhost flex]# cat test16.c|./a.out 
Error type 16 at Line 8:Duplicated name 'Position'
  • 1
  • 2
  • 3
[root@localhost flex]# cat test17.c 
int main()
{
    struct Position pos;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
[root@localhost flex]# cat test17.c|./a.out 
Error type 17 at Line 3:undefined structure 'Position'
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/909257
推荐阅读
相关标签
  

闽ICP备14008679号