【实验名称】 LL(1)递归下降子程序的实现
【实验目的】
结合书本p87页分析步骤,尝试就某一个类型,构造其递归下降子程序
【实验原理】
已知的文法为
“
S->FP
P->+FP
P->#
F->a
”
通过计算select集合,易证明是LL(1)文法
First(S)={a},First(P)={+,#},First(F)={a}
下面按照课本P88面构造递归下降程序。
【实验内容】
[if !supportLists]1. [endif]构造S()
S后面有两种可能,一种是匹配到F的first集合,一种是匹配不到,则直接报错。注意,MatchToken(a),应该发生在F()的函数种。
void S(){
ch=str.at(temp);
if(ch=='a'){
cout<<"S->FP;"<<endl;
F();
P();
}else{
error();
}
}
2.构造F()与P()的
F的比较简单,直接接受a的值就可以了,缜密一点也可以加上一个判断,不是a的话报错。
P的较为复杂一点,判断是否为‘+’后,还需要判断是不是到了‘a’,以执行F(),否则什么也不做。还要判断是否为‘#’,是的话直接接受‘#’
void F(){
cout<<"F->a;"<<endl;
MatchToken('a');
}
void P(){
ch= str.at(temp);
if(ch=='+'){
cout<<"P->+FP;"<<endl;
MatchToken('+');
// cout<<"hello"<
if (ch=='a'){
F();
P();
}
else{
// cout<
}
}
else if(ch=='#'){
cout<<"P->#;"<<endl;
MatchToken('#');
}
else{
error();
}
}
3.接受函数MatchToken()
就是接受字符,然后指针先后移一位,但是传值有点问题,所以我在判断接受后,重新将指针赋值了。
void MatchToken(char s)//判断字符串匹配
{
ch= str.at(temp);
if(ch!=s){
cout<<"syntax error"<<endl;
}
else
{
// cout<<"hello2"<
temp++;
ch= str.at(temp);
}
}
【小结或讨论】
这次实验本来是想实现对于所有的通用类型的LL(1)文法,构造出来一个通用的递归下降伪代码。但是实验难度比较大,我断断续续数个星期也没有解决关于First集合读取后再匹配问题。后来上课中有两处地方,给出了具体事例的LL(1)文法,一处是第四章,一处是第七章带语义分析的。就退而求其次,根据了一个具体的LL(1)文法,分析出来具体的递归下降程序。
在写程序时候,逻辑方面没有太大问题,因为在书本上给出了详尽的解释,在传参的时候出现了bug,后来我就直接从字符串中按位数取值,所以代码冗余了数行。
【实验截图】
[if !supportLists]1. [endif]a+a
[if !supportLists]2. [endif]a+a+a
[if !supportLists]3. [endif]a+b
代码:
/*
给定的LL(1)文法:
S->FP
P->+FP
P->#
F->a
First(S)={a},First(P)={+,#},First(F)={a}
*/
#include<iostream>
using namespace std;
int temp = 0;//指针
string str;//输入串
char ch;//指针指向的字符
void F();
void P();
void error(){
cout<<"error!";
exit(1);
}
void MatchToken(char s)//判断字符串匹配
{
ch= str.at(temp);
if(ch!=s){
cout<<"syntax error"<<endl;
}
else
{
// cout<<"hello2"<
temp++;
ch= str.at(temp);
}
}
void S(){
ch=str.at(temp);
if(ch=='a'){
cout<<"S->FP;"<<endl;
F();
P();
}else{
error();
}
}
void F(){
cout<<"F->a;"<<endl;
MatchToken('a');
}
void P(){
ch= str.at(temp);
if(ch=='+'){
cout<<"P->+FP;"<<endl;
MatchToken('+');
// cout<<"hello"<
if (ch=='a'){
F();
P();
}
else{
error();
}
}
else if(ch=='#'){
cout<<"P->#;"<
MatchToken('#');
}
else{
error();
}
}
int main(){
cin>>str;
str=str+'#';
S();
}