小记:
其实这个程序是编译原理这门课的综合实验,前段时间我申请免试又失败了,原因是有缺课,平时分不够,早上赖床现在尝到苦果我也是醉了……没办法,逼上梁山,只好攻克这个大boss以拿下免试资格。
选了一个最简单的文法,分析了1个多星期,终于决定开始要写的时候时间已经很紧了。
去实验室通宵了一晚,在宿舍熬了一晚,睡了3个小时就起来去验收了。还好是通过了,没白费劲。
不得不说,编译原理就是烧脑,知识点都比较抽象,如果数据结构和算法的基础打得不牢的话,实现起来会感到吃力。
再次感觉到了基础的重要性,这也是一个收获吧。
总的来说,相比较之前实现形式化的des加密算法,抽象的编译器更有难度,写完也更能让你感觉到提高。
ps:程序仅供参考,时间有限,没做太多测试。
功能:
给定一个简单语言的文法描述,本程序是该语言的编译器前端。
输入一个符合该文法规则的源文件,输出三地址形式的中间代码。
具体功能有词法分析,语法分析,分析流程显示,错误提示等。
程序运行结果:
源程序:
分析过程:
生成中间代码(三地址形式):
分析过程:
文法:
文法(消除左递归后)
Program->BEGIN Stmt-List END
Stmt-List->Stmt Stmt-List'
Stmt-List'->Stmt Stmt-List' | .
Stmt->Assign-stmt
Assign-stmt->ID = Expr
Expr->Term Expr'
Expr'->Add-Op Term Expr' | .
Term->Factor Term'
Term'->Multiple-Op Factor Term' | .
Factor->( Expr ) | ID | NUM
Add-Op->+ | -
Multiple-Op->* | /
FIRST集
First(Program)={BEGIN}
First(Stmt-List)={ID}
First(Stmt-List')={ ID,ε}
First(Stmt)={ ID}
First(Assign-stmt)={ ID}
First(Expr)={(,ID,NUM}
First(Expr')={+,-,ε}
First(Term)={(,ID,NUM}
First(Term')={*,/,ε}
First(Factor)={(,ID,NUM}
First(Add-Op)={+,-}
First(Multiple-Op)={*,/}
FOLLOW集
Follow(Program)={$}
Follow(Stmt-List)={END}
Follow(Stmt-List')={ END}
Follow(Stmt)={ ID,END}
Follow(Assign-stmt)={ ID,END }
Follow(Expr)={ ID,END ,)}
Follow(Expr')={ ID,END , )}
Follow(Term)={+,-, ID,END , )}
Follow(Term')={ +,-, ID,END , )}
Follow(Factor)={ *,/,+,-, ID,END , )}
Follow(Add-Op)={(,ID,NUM}
Follow(Multiple-Op)={ (,ID,NUM }
预测分析表:
代码:
1 //词法分析中' '代表空白字符,包括换行符,空格,制表符
2 //源程序格式:1、一行只能有一条语句;2、程序中可以有注释
3 #include <iostream>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stack>
7 #include <stdlib.h>
8 using namespace std;
9
10 char src[1000010]; //存储源代码
11 char TokenList_kind[1010][100]; //词法单元流 之 类别
12 int TokenList_value[1010]; //词法单元流 之 值
13 char WordList[1010][100]; //符号表 -- 由token_value指向
14 int LineList[1010]; //记录每一个token对应的行数 -- 由token_value指向
15 int TokenListPoint; //词法单元流指针
16 int WordListPoint; //符号表指针
17
18 int WordsPoint; //语法分析时的词法单元流指针
19
20 int tmpcnt; //三地址语句中寄存器的编号
21
22 int ExpTable[11][8] = { //用 表驱动法 读取表达式 ,状态转换表
23 2, -1, 1, -1, -1, -1, -1, 9,
24 2, -1, -1, -1, -1, -1, -1, 9,
25 2, -1, -1, 3, -1, -1, -1, 9,
26 4, 5, -1, -1, -1, -1, -1, 9,
27 4, -1, 8, -1, 6, -1, 10, 9,
28 -1, 5, 8, -1, 6, -1, 10, 9,
29 4, 5, -1, -1, -1, 7, -1, 9,
30 4, 5, -1, -1, -1, -1, -1, 9,
31 -1, -1, -1, -1, -1, -1, -1, -1,
32 -1, -1, -1, -1, -1, -1, -1, -1,
33 -1, -1, 8, -1, 6, -1, 10, 9
34 };
35
36 /*
37 文法
38 1 Program->BEGIN Stmt-List END
39 2 Stmt-List->Stmt Stmt-List'
40 3 Stmt-List'->Stmt Stmt-List' | .
41 4 Stmt->Assign-stmt
42 5 Assign-stmt->ID = Expr
43 6 Expr->Term Expr'
44 7 Expr'->Add-Op Term Expr' | .
45 8 Term->Factor Term'
46 9 Term'->Multiple-Op Factor Term' | .
47 10 Factor->( Expr ) | ID | NUM
48 11 Add-Op->+ | -
49 12 Multiple-Op->* | /
50
51 预测分析表
52 非终结符号 输入符号
53 BEGIN ‘+’ ‘-’ ‘*’ ‘/’ ( ) ‘=’ ID NUM END $
54 Program 1
55 Stmt-List 2
56 Stmt-List' 3 .
57 Stmt 4
58 Assign-stmt 5
59 Expr 6 6 6
60 Expr' 7 7 . . .
61 Term 8 8 8
62 Term' . . 9 9 . . .
63 Factor 10_1 10_210_3
64 Add-Op 11_1 11_2
65 Multiple-Op 12_1 12_2
66 */
67
68 char PreTab[12][12][100]={ //存储预测分析表
69 {"BEGIN Stmt-List END","","","","","","","","","","",""},
70 {"","","","","","","","","Stmt Stmt-List'","","",""},
71 {"","","","","","","","","Stmt Stmt-List'","",".",""},
72 {"","","","","","","","","Assign-stmt","","",""},
73 {"","","","","","","","","ID = Expr","","",""},
74 {"","","","","","Term Expr'","","","Term Expr'","Term Expr'","",""},
75 {"","Add-Op Term Expr'","Add-Op Term Expr'","","","",".","",".","",".",""},
76 {"","","","","","Factor Term'","","","Factor Term'","Factor Term'","",""},
77 {"",".",".","Multiple-Op Factor Term'","Multiple-Op Factor Term'","",".","",".","",".",""},
78 {"","","","","","( Expr )","","","ID","NUM","",""},
79 {"","+","-","","","","","","","","",""},
80 {"","","","*","/","","","","","","",""}
81 };
82
83 char Product[23][50]={ //记录产生式出现的字符串
84 "Program", //0
85 "Stmt-List", //1
86 "Stmt-List'", //2
87 "Stmt", //3
88 "Assign-stmt", //4
89 "Expr", //5
90 "Expr'", //6
91 "Term", //7
92 "Term'", //8
93 "Factor", //9
94 "Add-Op", //10
95 "Multiple-Op", //11
96
97 "BEGIN", //12
98 "+", //13
99 "-", //14
100 "*", //15
101 "/", //16
102 "(", //17
103 ")", //18
104 "=", //19
105 "ID", //20
106 "NUM", //21
107 "END" //22
108 };
109
110
111 //语法树节点
112 struct Node{
113 Node(char na[]){ //构造函数
114 strcpy(name,na);
115 wp = 0;
116 brother = NULL;
117 next = NULL;
118 }
119 char name[50];
120 int wp; //终结符在token流中的位置
121 Node* brother; //指向下一个兄弟节点
122 Node* next; //指向当前节点的孩子节点
123 }*root,*now,*p;
124
125 void Init()
126 {
127 memset(src,0,sizeof(src)); //初始化源代码字符数组
128 memset(TokenList_kind,0,sizeof(TokenList_kind)); //初始化词法单元流
129 memset(TokenList_value,0,sizeof(TokenList_value)); //初始化词法单元流
130 memset(WordList,0,sizeof(WordList)); //初始化符号表
131 TokenListPoint = 1;
132 WordListPoint = 1;
133
134 WordsPoint = 1;
135
136 //初始化指针
137 root = NULL;
138 now = NULL;
139 p = NULL;
140 tmpcnt = 1;
141 }
142
143 //--------------- 词法分析 start ---------------
144 void AddToken(char kind[],char value[],int line) //将<类别,值>放入token流中
145 {
146 strcpy(TokenList_kind[TokenListPoint],kind);
147 TokenList_value[TokenListPoint++] = WordListPoint;
148
149 strcpy(WordList[WordListPoint],value);
150 LineList[WordListPoint++] = line;
151 }
152
153 void strsub(char str1[],int start,int len,char str2[]) //截取str1的子字符串给str2
154 {
155 int i=0,j;
156 for(j=0;j<len;j++){
157 str2[i++] = str1[start+j];
158 }
159 str2[i] = '