实验目的
- 了解 LL(1)语法分析是如何根据语法规则逐一分析词法分析所得到的单词,检查语法错误,即掌握语法分析过程。
- 掌握LL(1)语法分析器的设计与调试。
实验内容
针对CP语言中简单算术表达式文法G[E]:
E→TE’
E’→ATE’|ε
T→FT’
T’→MFT’ |ε
F→(E) | i
A → + | -
M → * | /
求解相应的FIRST、FOLLOW集,构造预测分析表,并编写LL(1)语法分析程序,并给出测试句子的分析过程。(注:如果有选做专题7关于LL(1)文法判断的同学,可以将专题7的部分整合到这个实验的前面,自动产生预测分析表,相当于把这个程序做成一个通用的LL(1)分析器)
- 输入:是词法分析输出的二元组序列,即任意简单算术表达式经过专题1程序输出后得到的结果。【上述文法中i即对应词法分析的标识符, ±*/分别对应词法分析得到的运算符】
- 处理:基于分析表进行 LL(1)语法分析,判断其是否符合文法。
- 输出:串是否合法。
函数定义
int findH(char a) //在文法分析表中找到符号的对应行
int findL(char b) //在文法分析表中找到符号的对应列
int error(int i, int cnt, int len, char p[], char str[]) //报错
void analyze(char str[], int len) //进行LL(1)语法分析
int main() //语法分析主函数
程序流程图
源代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include <fstream>
using namespace std;
int flag=0;
char LL1[50][50][100] = { {"::TX" ,"::TX","null" ,"null","null","null","null","null",},
{"::FY" ,"::FY","null" ,"null", "null","null","null","null",},
{"null" ,"null" ,"::~","::ATX","::ATX","null","null","::~", },
{"null" ,"null" ,"null" ,"::+","::-","null","null","null", },
{"::i","::(E)","null" ,"null","null","null","null" ,"null", },
{"null","null","null" ,"null","null","::*","::/", "null", },
{"null","null","::~" ,"::~","::~","::MFY","::MFY", "::~" , }, };
char H[200] = "ETXAFMY";
char L[200] = "i()+-*/$";
stack<char>cmp;
int findH(char a)
{
for (int i = 0; i < 7; i++)//找到对应行
{
if (a == H[i])
{
return i;
}
}
return -1;
}
int findL(char b)
{
for (int i = 0; i < 8; i++)//找到对应列
{
if (b == L[i])
{
return i;
}
}
return -1;
}
/*int error(int i, int cnt, int len, char p[], char str[])
{
cout << cnt << "\t" << p << "\t";
for (int q = i; q < len; q++)
{
cout << str[q];
}
cout << "\t报错" << endl;
return len;
}*/
void analyze(char str[], int len)
{
int cnt = 1;//输出Step
int i = 0;
char p[200] = "$E";//输出stack
int pindex = 2;
cout << "Step\tStack\tString\tRule" << endl;
while (i < len)
{
int x, y;
char ch = cmp.top();
if (ch >= 'A'&&ch <= 'Z')
{
cmp.pop();
x = findH(ch);
y = findL(str[i]);
if (x != -1 && y != -1)
{
int len2 = strlen(LL1[x][y]);
if (strcmp(LL1[x][y], "null") == 0)
{
cout << cnt << "\t" << p << "\t";
for (int q = i; q < len; q++)
{
cout << str[q];
}
cout << "\t出错,已忽略当前符号" << endl;
cnt++;
flag=1;
cmp.push(ch);
i=i+1;
continue;
}
cout << cnt << "\t" << p << "\t";
if (p[pindex - 1] != '$')
{
p[pindex] = '\0';
pindex--;
}
if (LL1[x][y][2] != '~')
{
for (int q = len2 - 1; q > 1; q--)
{
p[pindex++] = LL1[x][y][q];
cmp.push(LL1[x][y][q]);//进栈
}
}
else
{
p[pindex] = '\0';
pindex;
}
for (int q = i; q < len; q++)
{
cout << str[q];//输出剩余输入串
}
cout << "\t" << ch << LL1[x][y] << endl;
}
else
{ cout << "\t出错,已忽略当前错误" << endl;
i=i+1;
//i = error(i, cnt, len, p, str);//未找到,报错
continue;
}
}
else
{
if (ch == str[i])
{
cmp.pop();
cout << cnt << "\t" << p << "\t";
if (ch == '$'&&str[i] == '$')
{
cout << "$\t接受" << endl;
return;
}
for (int q = i; q < len; q++)
{
cout << str[q];
}
cout << "\t" << ch << "匹配" << endl;
pindex--;
p[pindex] = '\0';
i++;
}
else
{ cout << "\t出错,已忽略当前错误" << endl;
i=i+1;
//i = error(i, cnt, len, p, str);//报错
continue;
}
}
cnt++;
}
}
int main()
{ string str1;
ifstream Prewords("test.txt", ios::in);
getline(Prewords, str1);
char *str=(char*)str1.c_str();
int len = strlen(str);
cmp.push('$');
cmp.push('E');
analyze(str, len + 1);
if(flag==1)
cout<<"\t当前语句不合法"<<endl;
else
cout<<"\t当前语句合法"<<endl;
system("pause");
return 0;
}
测试用例
注: X表示E’ Y表示T’ ~表示ε
1. i+i*i$
2. i++i$