# 基于C++实现的LL(1)语法分析程序
# 一、文法
**原文法**
```c++
E->E+T|E-T|T
T->T*F|T/F|F
F->id|(E)|num
其中: id: a-f, A-F,num:0-9
```
**消左递归**
```c++
E->TA A->+TA A->-TA A->e
T->FB B->*FB B->/FB B->e
F->i F->(E) F->n
其中:i:id, n:num, e:epsilon
```
# 二、FIRST 集和 FOLLOW 集
![](http://www.writebug.com/myres/static/uploads/2021/10/19/3b2599a965fca0d41354e5353a147923.writebug)
# 三、预测分析表
![](http://www.writebug.com/myres/static/uploads/2021/10/19/4f7c26d6b4cb2a984db97ae5ede8bfc6.writebug)
# 四、运行环境
- CodeBlocks-13.12 with GCC compiler from TDM-GCC (4.7.1, 32 bit)
# 五、输入输出设计
- 输入:文件“fin.txt”输入待分析串
- 输出:命令行界面输出预测分析表,LL(1)分析过程输出至“fout.txt”
# 六、主要数据结构
```c++
// 预测分析表
vector<vector<string>> table(5,vector<string>(9));
// 消除左递归后的文法产生式
vector<string> G;
// 文法符号到下标的转换字典
map<char, int> index;
// 终结符
string terminal("in+-*/()$");
// 非终结符
string nonTerminal("EATBF");
// 产生式右部符号串的 first 集
vector<string> First;
// 非终结符的 follow 集
vector<string> Follow;
```
# 七、核心算法
```c++
int main()
{
for(文法 G 每个产生式 itG,itFirst 为其右部符号串的 first 集){
x = itG 左部非终结符号的下标;
for(itFirst 中的每个终结符号 first){
y = 终结符号 first 的下标;
把 itG 加入分析表表 G[x][y];
}
if(终结符号 first == epsilon)
for(Follow 集中的每个符号 follow){
y = follow 的下标;
把 itG 加入分析表 G[x][y];
}
}
for(所有非终结符号的 Follow 集)
if(对应表项为空)
写入 synch;
将分析表输出到命令行界面;
return analysis();
}
```
```c++
int analysis(void)
{
从文件 fin.txt 读取待分析串到 s;
s 末尾加‘$’;
分析栈 vector<char> analyStack;
向栈压入‘$’、‘E’;
ip 指向 s 的第一个字符;
do{
top 是栈顶符号;
cur 是 ip 所指向的输入符号;
if(cur 是字母) cur = ‘i’;
if(cur 是数字) cur = ‘n’;
if(top 是终结符号或‘$’){
if(top == cur){从栈顶弹出 cur;ip 前移一个位置;}
else error;
}
else{
x = top 对应下标; y = cur 对应下标;
产生式 production = table[x][y];
if(production 非空){
栈顶弹出 cur;
把 production 右部逆序压栈;
输出 production;
}
else error;
}
}while(top != ‘$’);
}
```
# 八、测试
![](http://www.writebug.com/myres/static/uploads/2021/10/19/5d5a471615ba2effe952d1fd3ae76133.writebug)