概述
- 程序功能描述
- 程序目标
实现 LL(1)分析中控制程序( 表驱动程序),根据给定赋值语句的 LL(1)文法,完成分析过程。
输入:词法分析的二元式序列,输入结构如下:
typedef struct Dual
{
int Identifier;
char Character;
}
输出:输入串是否为该文法定义的算术表达式(bool)。
-
-
- 正则文法
-
G[S]: S→V=E
E→TE′
E′→ ATE′|ε
T→FT′
T′→ MFT′|ε
F→ (E)|i
A→+|-
M→*|/
V→i
(1) 递归下降分析程序应能发现简单的语法错误。
-
- 运行环境
语言:C++语言
编辑器:codeblocks
txt文件:用于保存词法分析结果,并作为语法分析的输入。
- 程序结构描述
- 设计方法
字符类型及字符串类型的识别使用穷举法搜索法。穷举搜索法是按某种顺序对所有可能的值进行逐个验证,从中找出符合条件的解。此方需要多重循环,简单易行,并且适合词法分析程序的查表原则。
正则文法的分析使用穷举搜索法及回溯法。穷举回溯法与以上同理,即对规则进行逐一的验证。回溯法主要用于/* */标记的注释的回溯,当无法匹配*/时,需要进行回溯,从/*标记的后一位重新开始进行扫描分析。
-
- 预处理
在程序中,由于没有编写产生FIRST集和FOLLOW集的函数,因此需要对文法进行预处理,得到其FIRST集和FOLLOW集,本程序的FIRST集和FOLLOW集如下:
元素 | FIRST集 | FOLLOW集 |
S→V=E | i, | # |
E→TE′ | (,i | ),# |
E′→ ATE′|ε | ε,+,- | ),# |
T→FT′ | (,i | +,-,),# |
T′→ MFT′|ε | *,/,ε | +,-,),# |
F→ (E)|i | (,i | *,/,+,-,),# |
A→+|- | +,- | (,i |
M→*|/ | *,/ | (,i |
V→i | i | = |
-
- 函数定义
- 主函数
- 函数定义
函数原型:int main()
参数:无
返回值:0(default)
功能说明:程序的入口,首先调用读文件程序读入文件,然后调用语法分析入口程序开始语法分析,若语法分析正确,最终输出结果将由主函数输出,否则将在中间环节返回错误信息。
-
-
- 读取文件函数
-
函数原型:bool ReadFile()
参数:无
返回值:是否正确读取文件内容
功能说明:将文件内容读入,并放入指定的数据结构中
-
-
- 游标移动函数
-
函数原型:void advance()
参数:无
返回值:无
功能说明:移动游标
-
-
- 各语句实现函数
-
函数原型:bool S();
bool E();
bool E1();
bool T();
bool T1();
bool F();
bool A();
bool M();
bool V();
参数:无
返回值:符合文法规则返回true,否则返回false
功能说明:分别定义各语句的文法规则,通过互相调用实现递归算法。
-
-
- 错误输出
-
函数原型:void error_report(string Wrong)
参数:错误位置信息
返回值:无
功能说明:若产生输入串与语法规则不符,则将被其他函数调用以输出错误信息
-
- 函数具体实现
- 主函数
- 源码:
- 主函数
- 函数具体实现
int main()
{
if(ReadFile())
{
cout << "file input:";
for(current = listdual.begin(); current != listdual.end(); ++current)
{
cout << (*current).Character <<" " ;
}
cout <<"n";
current = listdual.begin();
cout << "analysis:" << endl;
//从起始符号开始,自顶向下分析
if(S())
cout << "The result is Right!" << endl;
else
error_report("input");
}
else
{
error_report("ReadFile()");
}
return 0;
}
-
-
-
- 逻辑关系图:
-
-
图1 main函数调用逻辑关系图
-
-
- 文件识别函数
- 源码:
- 文件识别函数
-
bool ReadFile()
{
DUAL temp;
inFile.open("right.txt");
while(!inFile.eof())
{
inFile >> temp.Identifier >> temp.Character;
listdual.push_back(temp);
}
inFile.close();
return true;
}
-
-
- 游标移动函数
- 源码:
- 游标移动函数
-
void advance()
{
current++;
}
-
-
- 错误输出函数
- 源码:
- 错误输出函数
-
void error_report(string Wrong)
{
cout <<"ERROR:"<< Wrong << " error"<< endl;
}
-
-
- 产生式相关函数
-
// S->V=E
bool S()
{
if(current == listdual.end())
{
error_report("S() read file");
return false;
}
cout<<"S->V=E"<<endl;
if(!V())
return false;
if((*current).Character == '='){
cout<<"="<<endl;
advance();
}else return false;
if(!E())
return false;
return true;
}
//E→TE′
bool E(){
if(current == listdual.end())
{
error_report("E() read file");
return false;
}
cout<<"E->TE'"<<endl;
if(!T())
return false;
if(!E1())
return false;
return true;
}
// E′→ ATE′|ε
bool E1(){
if(current == listdual.end())
{
error_report("E1() read file");
return false;
}
else
{
if((*current).Character == '+' || (*current).Character == '-' )
{
cout<<"E'→ATE'"<<endl;
//按照匹配的候选式进行递归。
if(!A())
return false;
if(!T())
return false;
if(!E1())
return false;
}
else if((*current).Character == ')' || (*current).Character == '#')
cout<<"E'→ε"<<endl;
else
{
error_report("E1()");
return false;
}
}
return true;
}
// T→FT′
bool T(){
if(current == listdual.end())
{
error_report("T() read file");
return false;
}
cout<<"T→FT′"<<endl;
if(!F())
return false;
if(!T1())
return false;
return true;
}
//T′→ MFT′|ε
bool T1(){
if(current == listdual.end())
{
error_report("E1() read file");
return false;
}
else
{
if((*current).Character == '*' || (*current).Character == '/' )
{
cout<<"T′→ MFT′"<<endl;
//按照匹配的候选式进行递归。
if(!M())
return false;
if(!F())
return false;
if(!T1())
return false;
}
else if((*current).Character == ')' || (*current).Character == '#'||(*current).Character == '+'||(*current).Character == '-')
cout<<"T'→ε"<<endl;
else
{
error_report("E1()");
return false;
}
}
return true;
}
// F→ (E)|i
bool F()
{
if(current == listdual.end())
{
error_report("F() read file");
return false;
}
if((*current).Character == '(')
{
advance();
if(!E())
return false;
else if((*current).Character == ')')
{
advance();
cout << "F->(E)" <<endl;
}
else
return false;
}
if((*current).Character == 'i')
{
cout << "F->i" << endl;
advance();
}
return true;
}
// A→+|-
bool A()
{
if(current == listdual.end())
{
error_report("A() read file");
return false;
}
if((*current).Character == '+'||(*current).Character == '-')
{
cout<<"A→"<< (*current).Character <<endl;
}
else
{
error_report("A()");
return false;
}
advance();
return true;
}
// M→*|/
bool M()
{
if(current == listdual.end())
{
error_report("M() read file");
return false;
}
if((*current).Character == '*' || (*current).Character == '/')
{
cout << "M->" << (*current).Character << endl;
advance();
}
else
{
error_report("M()");
return false;
}
return true;
}
// V→i
bool V(){
if(current == listdual.end())
{
error_report("V() read file");
return false;
}
if((*current).Character == 'i'){
cout << "V->" << (*current).Character << endl;
advance();
}
else{
error_report("V()");
return false;
}
return true;
}
- 程序测试
- 测试用例
- 测试用例一:正确输入串
- 测试用例
1 i
2 =
3 (
4 i
5 +
6 i
7 )
8 /
9 i
10 #
测试结果:
测试用例二:错误输入串
1 i
2 +
3 i
4 (
3 i
4 #
-
- 测试结果
最后
以上就是霸气秀发为你收集整理的递归下降语法分析的全部内容,希望文章能够帮你解决递归下降语法分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复