目录
实验目的
实验内容
实验要求
运行结果示例
实验代码
运行结果
了解LL(1)分析器的基本构成及用自顶向下的LL(1)方法对表达式进行语法分析的方法,掌握LL(1)语法分析程序的构造方法。
根据LL(1)语法分析算法的基本思想,设计一个对给定文法进行LL(1)语法分析的程序,并用C语言编程实现。对于给定的输入串,能够识别该串是否位给定文法的句型。
输入一个LL(1)文法,构造相应的预测分析表。
从键盘读入输入串,由算法判断输入串是否为该文法的句子,若正确,就通过,否则就报错。
【参考说明】
语法分析主要是将从词法分析那里得来的记号构成一棵语法树。例:
SHMA#
adbe#
S->aH
H->aMd
H->d
M->Ab
M->
A->aM
A->e
**************************************************************
LL(1)文法分析器运行结果:
分析例句:(需要显示合法和不合法两种情况)
例: 分析例句:aaabd#
预测分析表输出:
……
aaabd# 是给定文法的句子
……
Ade#不是给定文法的句子
**************************************************************
运行成功以后,检查程序,并将运行结果截图打印粘贴到实验报告上。
本实验的文法:
对给定文法G[E]:
E->TA
A->+TA | $
T->FB
B->*FB | $
F-> i | (E)
其中,$表示空串。
#include
#include
#include
#include
#include
using namespace std;
//#pragma warning(disable:4996)
//本文法参考教材81面文法,将E'替换为A,T'替换为B
//作为示范的句子有
//i+i*i# (是文法的句子)
//i*i+i# (是文法的句子)
//i*(i+i)# (是文法的句子)
//i*)i+i# (不是文法的句子)
//i+i+*i# (不是文法的句子)
char Line[6] = "EATBF";//非终结符
char Row[7] = "i+*()#";//终结符
//表格数组,存储预测分析表
char ForcastTable[5][6][100] = { {"->TA","null" ,"null","->TA" ,"null","null" },
{"null","->+TA" ,"null","null" ,"->$", "->$" },
{"->FB","null" ,"null" ,"->FB","null","null" },
{"null","->$" ,"->*FB" ,"null" ,"->$","->$" },
{"->i" ,"null","null","->(E)" ,"null","null" } };
stackS;
int FindLine(char a)//找非终结符
{
for (int i = 0; i < 5; i++)
{
if (a == Line[i])
return i;
}
return -1;
}
int FindRow(char b)//找终结符
{
for (int i = 0; i < 6; i++)
{
if (b == Row[i])
return i;
}
return -1;
}
//获得一个句子中#前的部分,如句子为i+i*i##,则返回i+i*i#
char* GetStr(char* s)
{
char* p = strrchr(s, '#');//判断输入的是否含有'#'
if (p != NULL)//含有,则截取前面到#的字符串
{
int i = 0;
while (s[i] != '#')
{
i++;
}
char* str = new char[i + 2];
strncpy(str, s, i + 1);//截取s中的前i+1个元素分给str
str[i + 1] = '\0';
return str;
}
return s;
}
void AnalyzeProcess(char str[], int len)
{
int i = 0; //索引str的字符
while (true)
{
int x, y;
char ch = S.top();
if (ch >= 'A' && ch <= 'Z') //判断是否为非终结符
{
S.pop();
x = FindLine(ch);
y = FindRow(str[i]);
if (x != -1 && y != -1)//找到
{
// 输出匹配内容
if (ForcastTable[x][y] == "null") //找到对于表为空
{
printf("%s", str);
printf("%s\n\n", "不是给定文法的句子!");
exit(0);
}
else//找到信息
{
for (int q = strlen(ForcastTable[x][y]) - 1; q > 1; q--)//逆序入栈,改变字符串
{
S.push(ForcastTable[x][y][q]);
}
if (strcmp(ForcastTable[x][y], "->$") == 0)
{
S.pop();
}
}
}
else//未找到
{
printf("%s", str);
printf("%s\n\n", "不是给定文法的句子!");
break;
}
}
else//匹配串的第一个
{
if (ch == str[i])
{
S.pop();
if (ch = '#' && str[i] == '#')
{
printf("%s", str);
printf("%s\n\n", "是给定文法的句子!");
return;
}
i++;
}
else
{
printf("%s", str);
printf("%s\n\n", "不是给定文法的句子!");
return;
}
}
}
}
//输出分析表,并且分析
void ShowFunc()
{
printf("%s\n\n", "当前的预测分析表为:");
printf("%s", " ");
for (int a = 0; a < 6; a++)//输出预测分析表
{
printf("%5c", Row[a]);
}
printf("\n");
for (int i = 0; i < 5; i++)
{
printf("%c", Line[i]);
for (int j = 0; j < 6; j++)
{
printf("%6s", ForcastTable[i][j]);
}
printf("\n");
}
printf("%s\n\n", "请输入需要分析的语句,需要按quit/QUIT结束!");
while (true)//输入quit时跳出循环,程序运行结束
{
char str[200];
cin >> str;
if (strcmp(str, "quit") == 0 || strcmp(str, "QUIT") == 0)
{
printf("欢迎下次使用!!!");
return;
}
int len = strlen(GetStr(str));
S.push('#');
S.push('E');
AnalyzeProcess(GetStr(str), len + 1);
}
}
int main()
{
//输出分析表,并按输入分析,按quit退出
ShowFunc();
return 0;
}
先输出当前的预测分析表,然后输入待分析例句,给出相应结果分析结果,并输出,输入quit可以终止程序。
欧克,这个实验代码就丢在这里了,希望可以帮助到后面的学习者,欢迎大家关注!