编写语法分析程序
Note: Mr.JY的编译原理!
文法改造
1.文法
1) <program>→{<declaration_list><statement_list>}
2) <declaration_list>→<declaration_list><declaration_stat> | ε
3) <declaration_stat>→int ID;
4) <statement_list>→<statement_list><statement>| ε
5) <statement>→ <if_stat>|<while_stat>|<for_stat>|<read_stat>
|<write_stat>|< compound_stat > |<expression_stat>
6) <if_stat>→ if (<expr>) <statement >| if (<expr>) <statement >else < statement >
7) <while_stat>→ while (<expr >) < statement >
8) <for_stat>→ for (<expr>;<expr>;<expr>)<statement>
9) <write_stat>→write <expression>;
10) <read_stat>→read ID;
11)<compound_stat>→{<statement_list>}
12)<expression_stat>→< expression >;|;
13)< expression >→ ID=<bool_expr>|<bool_expr>
14)<bool_expr>→<additive_expr> |< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
15)< additive_expr>→< additive_expr>+<term>|< additive_expr>-<term>|< term >
16)< term >→< term >*<factor>|< term >/<factor>|< factor >
17)< factor >→(< expression >)|ID|NUM
2.消除左递归:
a.
原型:<declaration_list>→<declaration_list><declaration_stat> | ε
改造:<declaration_list> → A ,A →<declaration_stat>A|ε
b.
原形:<statement_list>→<statement_list><statement>| ε
改造:<statement_list> → B 。 B →<statement>B| ε
c.
原形:< additive_expr>→< additive_expr>+<term>|< additive_expr>-<term>|< term >
改造:< additive_expr> →< term >C 。 C →+<term>C|-<term>C|ε
3.提取公因式:
a.
原形:<bool_expr> →<additive_expr>|< additive_expr >(>|<|>=|<=|==|!=)< additive_expr >
改造:<bool_expr> →<additive_expr>E
E→ε|(>|<|>=|<=|==|!=)< additive_expr >
b.
原形:< term >→< term >*<factor>|< term >/<factor>|< factor >
改造:< term > →< factor >D
D →*<factor>D|/<factor>D|ε
3. <if_stat>→ if (<expr>) <statement >( ε|else < statement>)
不可提取公因式
< expression >→ ID=<bool_expr>|<bool_expr>
该文法解决方案: 程序设计时通过超前读一个符号来解决,假设识别出标识符的符号ID后,再读一个符号。假设这个符号是“=”,说明选择的是赋值表达式。 假设不是“=”,则说明选择的是布尔表达式
求First&Follow集
1) <program> →{<declaration_list><statement_list>}
First({<declaration_list><statement_list>})= { { }
2) <declaration_list> → A , A →<declaration_stat>A|ε
First(A)=First(<declaration_stat>A)= { int ,ε }
First(<declaration_stat>A)=First( int ID;)= { int }
Follow(A) ={ if,while,for,read,write,{,},;,ID,(,NUM}
3) <declaration_stat> →int ID;
First(int ID;)={int}
4)<statement_list> → B , B →<statement>B| ε
First(<statement>B)={ if,while,for,read,write,{,;,ID,NUM,( }
First(B) ={ if,while,for,read,write,{,;,ID, ε}
Follow(B) ={ } }
5)<statement> → <if_stat>|<while_stat>|<for_stat>|<read_stat>|
<write_stat>|< compound_stat > |<expression_stat>
First(<if_stat>)={if}
First(<while_stat>)={while}
First(<for_stat>)={for}
First(<read_stat>)={read}
First(<write_stat>)={write}
First(< compound_stat >)={{}
First(<expression_stat>)={ ;,ID,NUM,( }
6) <if_stat> → if (<expr>) <statement >| if (<expr>) <statement >else < statement >
First(if (<expr>) <statement >)={ if }
First(if (<expr>) <statement >else < statement >)={ if }
7) <while_stat> → while (<expr >) < statement >
First(while (<expr >) < statement >)={ while }
8) <for_stat> → for (<expr>;<expr>;<expr>)<statement>
First(for (<expr>;<expr>;<expr>)<statement>)={ for }
9) <write_stat> →write <expression>;
First(write <expression>;)={ write }
10) <read_stat> →read ID;
First(read ID;)={ read }
11)<compound_stat> →{<statement_list>}
First({<statement_list>})={{}
12)<expression_stat> →< expression >;|;
First(< expression >;)= {ID,NUM,(}
First(;)={;}
13)< expression > → ID=<bool_expr>|<bool_expr>
First(ID=<bool_expr>)={ID}
First(<bool_expr>)={ID,NUM,(}
14) <bool_expr> →<additive_expr>E , E→ε|(>|<|>=|<=|==|!=)< additive_expr >
First(<additive_expr>E)={ID,NUM,(}
First((>|<|>=|<=|==|!=)< additive_expr >)={>,<,>=,<=,==,!=}
First(ε)={ ε}
Follow(E)={;}
15)< additive_expr> →< term >C , C →+<term>C|-<term>C|ε
First(< term >C)={ID,NUM,(}
First(+<term>C)={+}
First(-<term>C)={-}
Follow(C)={;, ), (>|<|>=|<=|==|!=)}
16)< term > →< factor >D , D →*<factor>D|/<factor>D|ε
First(< factor >D)={ID,NUM,(}
First(*<factor>D)={*}
First(/<factor>D)={/}
First(ε)={ε}
Follow(D)={+,-, <,>,>=,<=,==,!=, ; , )}
17)< factor > →(< expression >)|ID|NUM
First((< expression >))={ ( }
First(ID)=ID
First(NUM)=NUM
代码实现
1.測试代码
{
int a;
int i;
int bc;
for (i=1; i <= 10; i=i+1)
{
;
a=a+i
b=b*i;
{
c=a+b;
}
}
if (a>b)
{
write a;
}
else
{
write b;
}
}
write c
}
2.实现代码
#include<stdio.h>
#include<ctype.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
int A();
int B();
int C();
int D();
int E();
int TESTparse();
int program();
int statement();
int statement_list();
int expression();
int expression_stat();
int declaration_stat();
int declaration_list();
int if_stat();
int for_stat();
int read_stat();
int write_stat();
int while_stat();
int compound_stat();
int term();
int factor();
int bool_expr();
int additive_expr();
int line;
char ch;
FILE *fp;//用于指向输入文件的指针
extern char Scanout[300];//保存词法分析输出文件名称
char token[20], token1[40];//token保存单词符号,token1保存单词值
int TESTparse()
{
int es = 0;
if ((fp = fopen(Scanout, "r")) == NULL)
{
printf("
Open %s error !
", Scanout);
es = 1;
}
printf("=========Result!=========
");
if (es == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = program();
}
fclose(fp);
return (es);
}
int program()
{
int es = 0;
if (strcmp(token, "{"))
{
printf("ERROR: Line %d Lack {
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = declaration_list();
if (es > 0)
{
return 1;
}
es = statement_list();
if (es > 0)
{
return 1;
}
if (strcmp(token, "}"))
{
printf("ERROR: Line %d Lack }
", line);
return 1;
}
ch = getc(fp);
while (ch != EOF)
{
if (ch != ' '&&ch != '
'&&ch != ' ')
{
printf("ERROR: Line %d Programma error!!
", line);
return (es = 1);
}
ch = getc(fp);
}
return (es);
}
int declaration_list()
{
int es = 0;
if (strcmp(token1, "int") == 0)
{
es = A();
return es;
}
else
{
printf("ERROR: Line %d Lack int
", line);
return 1;
}
}
int A()
{
int es = 0;
if (strcmp(token1, "int") == 0)
{
es = declaration_stat();
if (es > 0)
{
return 1;
}
es = A();
return (es);
}
else if
(
strcmp(token1, "if") == 0 ||
strcmp(token1, "while") == 0 ||
strcmp(token1, "for") == 0 ||
strcmp(token1, "read") == 0 ||
strcmp(token1, "write") == 0 ||
strcmp(token1, "{") == 0 ||
strcmp(token1, ";") == 0 ||
strcmp(token1, "ID") == 0 ||
strcmp(token1, "(") == 0||
strcmp(token1, "NUM") == 0 ||
strcmp(token1, "}") == 0
)
{
return 0;
}
else
{
printf("ERROR: Line %d Lack int||if||while||for||read||write||{||;||ID||(||NUM||}
", line);
return 1;
}
}
int declaration_stat()
{
if (strcmp(token, "int"))
{
printf("ERROR: Line %d Lack int
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
if (strcmp(token, "ID"))
{
printf("ERROR: Line %d Lack ID
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
if (strcmp(token, ";"))
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
int statement_list()
{
int es = 0;
if (
strcmp(token, "if") == 0 || strcmp(token, "while") == 0 ||
strcmp(token, "for") == 0 || strcmp(token, "read") == 0 ||
strcmp(token, "write") == 0 || strcmp(token, "ID") == 0 ||
strcmp(token, "{") == 0 || strcmp(token, ";") == 0 ||
strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0
)
{
es = B();
return es;
}
else
{
printf("ERROR: Line %d Lack if||while||for||read||write||{||;||ID||NUM||(
", line);
return 1;
}
}
int B()
{
int es = 0;
if (strcmp(token, "if") == 0 || strcmp(token, "while") == 0 ||
strcmp(token, "for") == 0 || strcmp(token, "read") == 0 ||
strcmp(token, "write") == 0 || strcmp(token, "ID") == 0 ||
strcmp(token, "{") == 0 || strcmp(token, ";") == 0 ||
strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0)
{
es = statement();
if (es > 0)
{
return 1;
}
es = B();
return (es);
}
else if (strcmp(token, "}") == 0)
{
return 0;
}
else
{
printf("ERROR: Line %d Lack if||while||for||read||write||{||;||ID||NUM||( ||}
", line);
return 1;
}
}
int statement()
{
int es = 0;
if (es == 0 && strcmp(token, "if") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = if_stat();
}
else if (es == 0 && strcmp(token, "while") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = while_stat();
}
else if (es == 0 && strcmp(token, "for") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = for_stat();
}
else if (es == 0 && strcmp(token, "read") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = read_stat();
}
else if (es == 0 && strcmp(token, "write") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = write_stat();
}
else if (es == 0 && strcmp(token, "{") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = compound_stat();
}
else if (es == 0 && strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0 || strcmp(token, ";") == 0)
{
es = expression_stat();
}
else
{
printf("ERROR: Line %d Lack if||while||for||read||write||{||;||ID||NUM||(
", line);
return 1;
}
return (es);
}
int if_stat()
{
int es = 0;
if (strcmp(token, "("))
{
printf("ERROR: Line %d Lack (
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ")"))
{
printf("ERROR: Line %d Lack )
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = statement();
if (es > 0)
{
return 1;
}
if (strcmp(token, "else") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = statement();
}
return (es);
}
int while_stat()
{
int es = 0;
if (strcmp(token, "("))
{
printf("ERROR: Line %d Lack (
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ")"))
{
printf("ERROR: Line %d Lack )
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = statement();
return (es);
}
int for_stat()
{
int es = 0;
if (strcmp(token, "("))
{
printf("ERROR: Line %d Lack (
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ";"))
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ";"))
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ")"))
{
printf("ERROR: Line %d Lack )
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = statement();
return (es);
}
int write_stat()
{
int es = 0;
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ";"))
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
int read_stat()
{
int es = 0;
if (strcmp(token, "ID"))
{
printf("ERROR: Line %d Lack ID
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
if (strcmp(token, ";"))
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
int compound_stat()
{
int es = 0;
es = statement_list();
if (es > 0)
{
return 1;
}
if (strcmp(token, "}"))
{
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
int expression_stat()
{
int es = 0;
if (strcmp(token, ";") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
else if (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0)
{
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ";") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
else
{
printf("ERROR: Line %d Lack ;
", line);
return 1;
}
}
else
{
printf("ERROR: Line %d Lack ;||ID||NUM||(
", line);
}
return 0;
}
int expression()
{
int es = 0, fileadd;
char token2[20], token3[40];
if (strcmp(token, "ID") == 0)
{
fileadd = ftell(fp);//记住当前文件位置
fscanf(fp, "%s%s%d
", &token2, &token3, &line);
if (strcmp(token2, "=") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = bool_expr();
if (es > 0)
{
return 1;
}
}
else
{
fseek(fp, fileadd, 0);//若非‘=’,则文件指针回到'='前的标识符
es = bool_expr();
if (es > 0)
{
return 1;
}
}
}
else
{
es = bool_expr();
if (es > 0)
{
return 1;
}
}
return 0;
}
int bool_expr()
{
int es = 0;
if (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "("))
{
es = additive_expr();
if (es > 0)
{
return 1;
}
es = C();
return (es);
}
else
{
printf("ERROR: Line %d Lack ID||NUM||(
", line);
return 1;
}
}
int C()
{
int es = 0;
if (
strcmp(token, ">") == 0 ||
strcmp(token, ">=") == 0 ||
strcmp(token, "<") == 0 ||
strcmp(token, "<=") == 0 ||
strcmp(token, "==") == 0 ||
strcmp(token, "!=") == 0
)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = additive_expr();
if (es > 0)
{
return 1;
}
return 0;
}
else if (strcmp(token, ";") == 0 || strcmp(token, ")") == 0)
{
return 0;
}
else
{
printf("ERROR: Line %d Lack )||>||<||>=||<==||==||!=||;
", line);
return 1;
}
}
int additive_expr()
{
int es = 0;
if (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0)
{
es = term();
if (es > 0)
{
return 1;
}
es = D();
return (es);
}
else
{
printf("ERROR: Line %d Lack ID||NUM||(
", line);
return 1;
}
}
int D()
{
int es = 0;
if (strcmp(token, "+") == 0 || strcmp(token, "-") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = term();
if (es > 0)
{
return 1;
}
es = D();
return (es);
}
else if
(
strcmp(token, ";") == 0 || strcmp(token, ")") == 0 ||
strcmp(token, ">") == 0 || strcmp(token, ">=") == 0 ||
strcmp(token, "<") == 0 || strcmp(token, "<=") == 0 ||
strcmp(token, "==") == 0 || strcmp(token, "!=") == 0
)
{
return 0;
}
else
{
printf("ERROR: Line %d Lack +||-||;||)||<||>||<=||>=||==||!=
", line);
return 1;
}
}
int term()
{
int es = 0;
if (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0 || strcmp(token, "(") == 0)
{
es = factor();
if (es > 0)
{
return 1;
}
es = E();
return (es);
}
else
{
printf("ERROR: Line %d Lack ID||NUM||(
", line);
return 1;
}
}
int E()
{
int es = 0;
if (strcmp(token, "*") == 0 || strcmp(token, "/") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = factor();
if (es > 0)
{
return 1;
}
es = E();
return (es);
}
else if
(
strcmp(token, ";") == 0 || strcmp(token, ")") == 0 ||
strcmp(token, "+") == 0 || strcmp(token, "-") == 0 ||
strcmp(token, ">") == 0 || strcmp(token, ">=") == 0 ||
strcmp(token, "<") == 0 || strcmp(token, "<=") == 0 ||
strcmp(token, "==") == 0 || strcmp(token, "!=") == 0
)
{
return 0;
}
else
{
printf("ERROR: Line %d Lack *||/||;||)||>||<||==||!=||>=||<=
", line);
return 1;
}
}
int factor()
{
int es = 0;
if (strcmp(token, "(") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
es = expression();
if (es > 0)
{
return 1;
}
if (strcmp(token, ")"))
{
printf("ERROR: Line %d )
", line);
return 1;
}
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
else if (strcmp(token, "ID") == 0 || strcmp(token, "NUM") == 0)
{
fscanf(fp, "%s%s%d
", &token, &token1, &line);
return 0;
}
else
{
printf("ERROR: Line %d ( || ID || NUM
", line);
return 1;
}
}