-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.y
157 lines (138 loc) · 7.64 KB
/
parser.y
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
%error-verbose
%locations
%{
#include "stdio.h"
#include "math.h"
#include "string.h"
#include "def.h"
extern int yylineno;
extern char *yytext;
extern FILE *yyin;
int yylex();
void yyerror(const char* fmt, ...);
void display(struct node *,int);
void semantic_Analysis0(struct node *);
%}
%union {
char type_char;
int type_int;
float type_float;
char type_id[32];
struct node *ptr;
};
// %type 定义非终结符的语义值类型
%type <ptr> program ExtDefList ExtDef Specifier ExtDecList FuncDec CompSt VarList VarDec ParamDec Stmt StmList DefList Def DecList Dec Exp Args
//% token 定义终结符的语义值类型
%token <type_int> INT //指定INT的语义值是type_int,有词法分析得到的数值
%token <type_char> CHAR
%token <type_id> ID RELOP TYPE //指定ID,RELOP 的语义值是type_id,有词法分析得到的标识符字符串
%token <type_float> FLOAT //指定ID的语义值是type_id,有词法分析得到的标识符字符串
%token LP RP LC RC SEMI COMMA //用bison对该文件编译时,带参数-d,生成的exp.tab.h中给这些单词进行编码,可在lex.l中包含parser.tab.h使用这些单词种类码
%token PLUS MINUS STAR DIV ASSIGNOP AND OR NOT IF ELSE WHILE RETURN INC DEC FOR PLUSEQ MINUSEQ STAREQ DIVEQ BREAK CONTINUE
%left ASSIGNOP
%left OR
%left AND
%left RELOP
%left PLUS MINUS
%left STAR DIV PLUSEQ MINUSEQ STAREQ DIVEQ
%right UMINUS NOT
%nonassoc LOWER_THEN_ELSE
%nonassoc ELSE
%nonassoc INC DEC
%%
program: ExtDefList { display($1,0); semantic_Analysis0($1);} //显示语法树,语义分析
;
ExtDefList: {$$=NULL;}
| ExtDef ExtDefList {$$=mknode(EXT_DEF_LIST,$1,$2,NULL,yylineno);} //每一个EXTDEFLIST的结点,其第1棵子树对应一个外部变量声明或函数
;
ExtDef: Specifier ExtDecList SEMI {$$=mknode(EXT_VAR_DEF,$1,$2,NULL,yylineno);} //该结点对应一个外部变量声明
|Specifier FuncDec CompSt {$$=mknode(FUNC_DEF,$1,$2,$3,yylineno);} //该结点对应一个函数定义
| error SEMI {$$=NULL; }
;
Specifier: TYPE {$$=mknode(TYPE,NULL,NULL,NULL,yylineno);strcpy($$->type_id,$1);$$->type=!strcmp($1,"int")?INT:($$->type=!strcmp($1,"char")?CHAR:FLOAT);}
;
ExtDecList: VarDec {$$=$1;} /*每一个EXT_DECLIST的结点,其第一棵子树对应一个变量名(ID类型的结点),第二棵子树对应剩下的外部变量名*/
| VarDec COMMA ExtDecList {$$=mknode(EXT_DEC_LIST,$1,$3,NULL,yylineno);}
;
VarDec: ID {$$=mknode(ID,NULL,NULL,NULL,yylineno);strcpy($$->type_id,$1);} //ID结点,标识符符号串存放结点的type_id
;
FuncDec: ID LP VarList RP {$$=mknode(FUNC_DEC,$3,NULL,NULL,yylineno);strcpy($$->type_id,$1);}//函数名存放在$$->type_id 有参函数
|ID LP RP {$$=mknode(FUNC_DEC,NULL,NULL,NULL,yylineno);strcpy($$->type_id,$1);}//函数名存放在$$->type_id 无参函数
;
VarList: ParamDec {$$=mknode(PARAM_LIST,$1,NULL,NULL,yylineno);}
| ParamDec COMMA VarList {$$=mknode(PARAM_LIST,$1,$3,NULL,yylineno);}
;
ParamDec: Specifier VarDec {$$=mknode(PARAM_DEC,$1,$2,NULL,yylineno);}
;
CompSt: LC DefList StmList RC {$$=mknode(COMP_STM,$2,$3,NULL,yylineno);}
;
StmList: {$$=NULL; }
| Stmt StmList {$$=mknode(STM_LIST,$1,$2,NULL,yylineno);}
;
Stmt: Exp SEMI {$$=mknode(EXP_STMT,$1,NULL,NULL,yylineno);}
| CompSt {$$=$1;} //复合语句结点直接最为语句结点,不再生成新的结点
| RETURN Exp SEMI {$$=mknode(RETURN,$2,NULL,NULL,yylineno);}
| IF LP Exp RP Stmt %prec LOWER_THEN_ELSE {$$=mknode(IF_THEN,$3,$5,NULL,yylineno);}
| IF LP Exp RP Stmt ELSE Stmt {$$=mknode(IF_THEN_ELSE,$3,$5,$7,yylineno);}
| WHILE LP Exp RP Stmt {$$=mknode(WHILE,$3,$5,NULL,yylineno);}
| BREAK SEMI {$$=mknode(BREAK,NULL,NULL,NULL,yylineno);}
| CONTINUE SEMI {$$=mknode(CONTINUE,NULL,NULL,NULL,yylineno);}
| FOR LP Exp SEMI Exp SEMI Exp RP Stmt {$$=mknode(FOR,$3,$5,mknode(FOR,$7,$9,NULL,yylineno),yylineno);}
| FOR LP SEMI Exp SEMI Exp RP Stmt {$$=mknode(FOR,NULL,$4,mknode(FOR,$6,$8,NULL,yylineno),yylineno);}
| FOR LP Exp SEMI Exp SEMI RP Stmt {$$=mknode(FOR,$3,$5,mknode(FOR,NULL,$8,NULL,yylineno),yylineno);}
| FOR LP SEMI Exp SEMI RP Stmt {$$=mknode(FOR,NULL,$4,mknode(FOR,NULL,$7,NULL,yylineno),yylineno);}
;
DefList: {$$=NULL; }
| Def DefList {$$=mknode(DEF_LIST,$1,$2,NULL,yylineno);}
;
Def: Specifier DecList SEMI {$$=mknode(VAR_DEF,$1,$2,NULL,yylineno);}
;
DecList: Dec {$$=mknode(DEC_LIST,$1,NULL,NULL,yylineno);}
| Dec COMMA DecList {$$=mknode(DEC_LIST,$1,$3,NULL,yylineno);}
;
Dec: VarDec {$$=$1;}
| VarDec ASSIGNOP Exp {$$=mknode(ASSIGNOP,$1,$3,NULL,yylineno);strcpy($$->type_id,"ASSIGNOP");}
;
Exp: Exp ASSIGNOP Exp {$$=mknode(ASSIGNOP,$1,$3,NULL,yylineno);strcpy($$->type_id,"ASSIGNOP");}//$$结点type_id空置未用,正好存放运算符
| Exp AND Exp {$$=mknode(AND,$1,$3,NULL,yylineno);strcpy($$->type_id,"AND");}
| Exp OR Exp {$$=mknode(OR,$1,$3,NULL,yylineno);strcpy($$->type_id,"OR");}
| Exp RELOP Exp {$$=mknode(RELOP,$1,$3,NULL,yylineno);strcpy($$->type_id,$2);} //词法分析关系运算符号自身值保存在$2中
| Exp PLUS Exp {$$=mknode(PLUS,$1,$3,NULL,yylineno);strcpy($$->type_id,"PLUS");}
| Exp MINUS Exp {$$=mknode(MINUS,$1,$3,NULL,yylineno);strcpy($$->type_id,"MINUS");}
| Exp STAR Exp {$$=mknode(STAR,$1,$3,NULL,yylineno);strcpy($$->type_id,"STAR");}
| Exp DIV Exp {$$=mknode(DIV,$1,$3,NULL,yylineno);strcpy($$->type_id,"DIV");}
| Exp PLUSEQ Exp {$$=mknode(PLUSEQ,$1,$3,NULL,yylineno);strcpy($$->type_id,"PLUSEQ");}
| Exp MINUSEQ Exp {$$=mknode(MINUSEQ,$1,$3,NULL,yylineno);strcpy($$->type_id,"MINUSEQ");}
| Exp STAREQ Exp {$$=mknode(STAREQ,$1,$3,NULL,yylineno);strcpy($$->type_id,"STAREQ");}
| Exp DIVEQ Exp {$$=mknode(DIVEQ,$1,$3,NULL,yylineno);strcpy($$->type_id,"DIVEQ");}
| LP Exp RP {$$=$2;}
| MINUS Exp %prec UMINUS {$$=mknode(UMINUS,$2,NULL,NULL,yylineno);strcpy($$->type_id,"UMINUS");}
| NOT Exp {$$=mknode(NOT,$2,NULL,NULL,yylineno);strcpy($$->type_id,"NOT");}
| INC Exp {$$=mknode(INC,NULL,$2,NULL,yylineno);strcpy($$->type_id,"PreINC");}
| DEC Exp {$$=mknode(DEC,NULL,$2,NULL,yylineno);strcpy($$->type_id,"PreDEC");}
| Exp INC {$$=mknode(INC,$1,NULL,NULL,yylineno);strcpy($$->type_id,"AftINC");}
| Exp DEC {$$=mknode(DEC,$1,NULL,NULL,yylineno);strcpy($$->type_id,"AftDEC");}
| ID LP Args RP {$$=mknode(FUNC_CALL,$3,NULL,NULL,yylineno);strcpy($$->type_id,$1);}
| ID LP RP {$$=mknode(FUNC_CALL,NULL,NULL,NULL,yylineno);strcpy($$->type_id,$1);}
| ID {$$=mknode(ID,NULL,NULL,NULL,yylineno);strcpy($$->type_id,$1);}
| CHAR {$$=mknode(CHAR,NULL,NULL,NULL,yylineno);$$->type_char=$1;$$->type=CHAR;}
| INT {$$=mknode(INT,NULL,NULL,NULL,yylineno);$$->type_int=$1;$$->type=INT;}
| FLOAT {$$=mknode(FLOAT,NULL,NULL,NULL,yylineno);$$->type_float=$1;$$->type=FLOAT;}
;
Args: Exp COMMA Args {$$=mknode(ARGS,$1,$3,NULL,yylineno);}
| Exp {$$=mknode(ARGS,$1,NULL,NULL,yylineno);}
;
%%
int main(int argc, char *argv[]){
return yyparse();
}
#include<stdarg.h>
void yyerror(const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "Grammar Error at Line %d Column %d: ", yylloc.first_line,yylloc.first_column);
fprintf(stderr,"yytext:%s\n",yytext);
vfprintf(stderr, fmt, ap);
fprintf(stderr, ".\n");
}