动易网站官网,网络营销推广策划方案,游戏合作渠道,河北项目网手机版一、实验内容与要求 先从键盘读入要分析的文法#xff0c;由程序自动构造FIRST、FOLLOW 集以及SELECT集合#xff0c;判断是否为LL (1)文法。 分析文法为G[E]#xff1a; #xff08;0#xff09;E→ TE’ #xff08;1#xff09;E’→ TE’ #xff08;2#xff…
一、实验内容与要求 先从键盘读入要分析的文法由程序自动构造FIRST、FOLLOW 集以及SELECT集合判断是否为LL (1)文法。 分析文法为G[E] 0E→ TE’ 1E’→ TE’ 2E’→ε 3T→ FT’ 4T’→ *FT’ 5T’→ε 6F→ (E) 7F→a 若符合LL (1)文法由程序自动构造LL (1)分析表;由算法判断给定的输入符号串a*(aa)是否为该文法的句型。 二、实验代码
#includeiostream
#includestdio.h
#includevector
#includestring
#includestack
#includemap
#includeiomanip
#includecstring
#includecstdlib
#include bits/ios_base.h
using namespace std;
mapchar,intgetnum;
vectorchargetzf;
vectorstringproce(10);
vectorstringfirst(20);
vectorstringfollow(20);
int table[100][100]; //预测分析表
int num;
int numv;//终结符的数量-1
char j[2];//读取终结符、非终结符与产生式
void read()
{char c;int i0;int n0;cout******************************LL(1)语法分析****************************endl; cout注意E用H代替T‘用J代替空串用代替 endl;cout请输入产生式的集合空用表示,输入一条产生式后换行最后以end结束:endl;string ss;string dd;int j0;int y0;while(cinssss!end){ dd.clear();ddss[0];proce[j]dd;for(i3;iss.length();i){ if(ss[i]!|){dd.clear();ddss[i];proce[j]dd;} else{dd.clear();ddss[0];ddss[i];proce[j]dd;} }j;
}
getnum[#]0;//#代表结束标志
// getzf[0]#;没有定义数组大小的时候这样输入是错误的
getzf.push_back(#);
//终结符压栈
for(int i0;iproce.size();i)
{for(int k0;kproce[i].length();k){if(proce[i][k]!-proce[i][k]!|){if(proce[i][k]64||proce[i][k]90){for( y0;ygetzf.size();y){if(proce[i][k]getzf[y]) break;}if(ygetzf.size()k!2){//这里让k!2是不让第三位置的进去 getnum[proce[i][k]]n;getzf.push_back(proce[i][k]);}}} }
}getnum[]n;numvn;//终结符的数量等于当前n的值 getzf.push_back();//非终结符压栈 for(int i0;iproce.size();i){for(int k0;kproce[i].length();k){if(proce[i][k]!-proce[i][k]!|proce[i][k]!){if(proce[i][k]64proce[i][k]91){for( y0;ygetzf.size();y){if(proce[i][k]getzf[y]) break;}if(ygetzf.size()){getnum[proce[i][k]]n;numn;//终结符加非终结符的数量等于当前i的值 getzf.push_back(proce[i][k]);}}} }}
}//给终结符的first数组赋值
void get_firstT()
{int i;//不能在下面int //先给终结符的first数组赋值for( i1;inumv;i) {itoa(i,j,10);first[i]j;//之前写的是first[i].push_back(j[0])是错的字符串数组的输入不需要加下标,且如果是j[0]一个字符不能装到一个字符串当中去 }
}//给非终结符的first数组赋值
string get_firstF(int *a)
{//犯了一个错误下面的a没有加* for(int i0;iproce.size();i){if(getnum[proce[i][0]]*a){if(getnum[proce[i][1]]numv){itoa(getnum[proce[i][1]],j,10); first[*a]j;}else{ //first[getnum[proce[i][0]]].clear();first[getnum[proce[i][0]]]get_firstF(getnum[proce[i][1]]);}} }return first[*a];
} //求follow集
void get_follow(int *a){
//犯了一个错误以stirng开头但是没有返回值 int i,j1;int flag0;for(i0;iproce.size();i){for(j11;j1proce[i].length();j1){if(getnum[proce[i][j1]]*a)//这地方应该是j1我写成了k {if(j1proce[i].length()-1){if(getnum[proce[i][j1]]!getnum[proce[i][0]])follow[*a]follow[getnum[proce[i][0]]]; }else {if(getnum[proce[i][j11]]numv) {itoa(getnum[proce[i][j11]],j,10);follow[*a]j;}else{for(int jj0;jjfirst[getnum[proce[i][j11]]].size();jj) {if(atoi(first[getnum[proce[i][j11]]][jj])numv)//等于空时follow[*a]follow[getnum[proce[i][0]]];elsefollow[*a]first[getnum[proce[i][j11]]][jj];}flag1;//标志位如果已经找到*a后面的非终结符就可以停止了 }}}} if(flag1) break; //停止寻找 }
}//求预测分析表
void get_table()
{memset(table,-1,sizeof(table));//刚开始tableM没有初始化导致本该是空格的地方出现E-TA for(int i0;iproce.size();i) //扫所有产生式{if(proce[i][1]) //直接推出空字的特判下follow集产生式左边的vn中元素填{string flwfollow[getnum[proce[i][0]]];for(int k0;kflw.size();k){table[getnum[proce[i][0]]][flw[k]-0]i;}}string tempsfirst[getnum[proce[i][1]]];for(int j0;jtemps.size();j) //考察first集{if(atoi(temps[j])!numv) {// table[getnum[proce[i][0]]][atoi(temps[j])]i;//atoi不能这么用他表示的是从当前位一直到末位 table[getnum[proce[i][0]]][temps[j]-0]i;}else //有空字的考察follw集{string flwfollow[getnum[proce[i][1]]];for(int k0;kflw.size();k){table[getnum[proce[i][0]]][flw[k]-0]i;}}}}
}//由对应下标获得对应产生式
string get_proce(int i)
{if(i0)return ; //无该产生式string ss;ssproce[i][0];ss-; //把-要加上 for(int j1;jproce[i].size();j)ssproce[i][j];return ss;
}//输出预测分析表
void print_table()
{cout该文法对应的预测分析表如下endl;cout________________________________________________________endl;for(int i0;inumv;i)cout\tgetzf[i];coutendl;for(int inumv1;inum;i){coutendl________________________________________________________endl;coutgetzf[i];for(int j0;jnumv;j){cout\tget_proce(table[i][j]);}}coutendl________________________________________________________endl;coutendl;
}//打印栈中元素
void print_stack(stackcharsta){int lengthsta.size();//栈中元素数目vectorchartemp;for(int i0;ilength;i){//coutsta.top();temp.push_back(sta.top());sta.pop();} for(int jlength-1;j0;j--){couttemp[j];}cout\t\t;
} //打印判定串的当前元素
void print_string(string str,int index){int lengthstr.size();for(int iindex;ilength;i){coutstr[i];}cout#;cout\t\t;
}//分析word符号串的合法性(关键)
string word;
bool analyze()
{stackcharsta;//分析栈 sta.push(#); //#最先进栈 sta.push(proce[0][0]);//将开始符压入分析栈中进行初始化 int i0;int count1;//步骤计数 printf(步骤\t\t分析栈\t\t判定串\t\t使用规则\n);//表头 while(!sta.empty()){coutcount\t\t;print_stack(sta);//打印当前分析栈 print_string(word,i);//打印当前判定串 int cursta.top();//取出分析栈的栈顶元素 sta.pop();if(curword[i]) //如果分析栈的栈顶元素与判定串的第一个元素相同即是终结符的话则匹配成功分析栈弹出栈顶元素 {i;printf(匹配出栈\n);}else if(cur#) //如果分析栈的栈顶元素为#则表面分析结束{return 1;}else if(table[getnum[cur]][getnum[word[i]]]!-1) //查找对应的预测分析表 {int ktable[getnum[cur]][getnum[word[i]]];coutproce[k][0]-;for(int j1;jproce[k].size();j)coutproce[k][j];coutendl;//将使用的产生式逆序加入分析栈中以取代上一个出栈的元素 for(int jproce[k].size()-1;j0;j--) { if(proce[k][j]!)sta.push(proce[k][j]);}}else {return 0;}count;}return 1;
}//输入待判断的符号串
void scanf()
{cout请输入待判定的符号串;cinword;cout判断分析表如下endl; if(analyze())coutendl综上该符号串有效是该文法的句型endl;else coutendl出错该符号串不是该文法的句型endl;
}int main()
{int k;int j;read();//终结符的first集 get_firstT();//非终结符的first集 for(knumv1;knum;k) //犯了一个错误numv的位置写成7 {get_firstF(k);}follow[numv1]0; //这地方加的是0而不是# for(knumv1;knum;k) //犯了一个错误numv的位置写成7 {get_follow(k);}coutendl; get_table();print_table();scanf(); return 0;
}
/*测试数据
注意E用H代替T‘用J代替空串用代替
E-TH
H-TH
H-
T-FJ
J-*FJ
J-
F-(E)
F-a
end
*/三、实验结果 END.