一、实验目的
通过预测分析算法的设计与实现,加深对自上而下语法分析方法的理解,尤其是对自上而下分析条件的理解。
二、实验要求
输入文法及待分析的输入串,输出其预测分析过程及结果。
三、实验步骤
1. 参考数据结构
(1)/*定义产生式的语法集结构*/
typedef struct{
char formula[200];//产生式
}grammarElement;
grammarElement gramOldSet[200];//原始文法的产生式集
(2)/*变量定义*/
char terSymbol[200];//终结符号
char non_ter[200];//非终结符号
char allSymbol[400];//所有符号
char firstSET[100][100];//各产生式右部的FIRST集
char followSET[100][100];//各产生式左部的FOLLOW集
int M[200][200];//分析表
2. 判断文法的左递归性,将左递归文法转换成非左递归文法。(该步骤可以省略,直接输入非左递归文法)。
3.根据文法求FIRST集和FOLLOW集。
(1)/*求 First 集的算法*/
(2)/*求 FOLLOW 集的算法*/
(这两个算法参见陈火旺版编译原理)
4.构造预测分析表。
(参见)
5.构造总控程序。
程序流程图如图1所示:
图1
6.对给定的输入串,给出分析过程及结果。
四、实验报告要求
1.写出编程思路、源代码(或流程图);
2.写出上机调试时发现的问题,以及解决的过程;
3.写出你所使用的测试数据及结果;
4.谈谈你的体会。
5.上机8小时,完成实验报告2小时。
编码实现
#include<iostream>
#include<cstring>
#include<string>
#include<stack>
// #include<string.h>
using namespace std;
typedef struct{
string formula;//产生式
}grammarElement;
grammarElement gramOldSet[200];
string terSymbol;//终结符号
string non_ter;//非终结符号
string allSymbol;//所有符号
string firstSET[100];//各产生式右部的FIRST集
string followSET[100];//各产生式左部的FOLLOW集
bool flag[100]={0};
int M[200][200];//分析表
int n=0;
// void grammerIn();
void First(char c);
void Follow(char nont);
void Table();
bool Control();
int addF(string &s, char c);
int is_terSymbol(char c);
int is_non_ter(char c);
bool forkong(char c);
void print(stack<char> S, string str);
int main(){
cout << "non_ter: ";
cin >> non_ter;
cout << "ter: ";
cin >> terSymbol;
cout<<"num: ";
cin>> n;
for(int i=0;i<n;i++){
cin>>gramOldSet[i].formula;
}
// cout<<gramOldSet[0].formula<<endl;
terSymbol.push_back('#');
for(int i=0;i<n;i++){
if (flag[is_non_ter(gramOldSet[i].formula[0])] == 0){
First(gramOldSet[i].formula[0]);
}
}
for(int i=0;i<non_ter.size();i++) cout<<firstSET[i]<<endl;
for(int i=0;i<n;i++){
if (flag[is_non_ter(gramOldSet[i].formula[0])] == 1){
Follow(gramOldSet[i].formula[0]);
}
}
for(int i=0;i<non_ter.size();i++) cout<<followSET[i]<<endl;
Table();
for(int i=0;i<non_ter.size();i++){
for(int j=0;j<terSymbol.size();j++){
cout.width(4);
cout<<M[i][j];
}
cout<<endl;
}
Control();
return 0;
}
void First(char nont){
// char *p = firstSET[is_non_ter(nont)]; //first集存放位置
int k=0;
for(int i=0; i<n ;i++) { //在输入的产生式中查找,不是就continue
if(gramOldSet[i].formula[0] == nont) {
char *pfml = &gramOldSet[i].formula[3]; //产生式的第一个符号
int isnt = is_non_ter(*pfml);
int ist = is_terSymbol(*pfml);
if( ist >= 0 || (gramOldSet[i].formula[3] == '$' && gramOldSet[i].formula.size()==4 ) ){ //第一个字符是终结符或只能推出空
addF( firstSET[is_non_ter(nont)] , gramOldSet[i].formula[3]);
}
else if(isnt>=0){ //第一个字符是非终结符
//产生式的第一个字符为本身
if(non_ter[isnt] == nont){
continue;
}
else{
//没有找过first集
if(flag[isnt]==0){
First(gramOldSet[i].formula[3]);
}
if(flag[isnt]==1){
for(int j=0; j<firstSET[isnt].size(); j++)
addF(firstSET[is_non_ter(nont)] , firstSET[isnt][j]);
}
//可推出空字
for(int m=4; ;m++){
if(forkong(*pfml) && m<gramOldSet[i].formula.size()){ //且不以此符号结尾
pfml++;
}else if(forkong(*pfml) && m==gramOldSet[i].formula.size()){ //以此符号结尾
addF(firstSET[is_non_ter(nont)] , '$');
break;
}else break;
if(flag[ is_non_ter(*pfml) ]==0){ //当前符号没有求first集
First(*pfml);
}
if(flag[ is_non_ter(*pfml) ]==1){
for(int j=0; j<firstSET[ is_non_ter(*pfml) ].size(); j++)
addF(firstSET[is_non_ter(nont)] , firstSET[ is_non_ter(*pfml) ][j]);
}
}
}
}
}
else {
continue;
}
}
//标记该非终结符已经查找过first集
flag[is_non_ter(nont)]=1;
}
void Follow(char nont){
for(int i=0;i<n;i++){
if(gramOldSet[i].formula[0] == nont){
char *pfml;
if(i==0){
addF(followSET[is_non_ter(nont)] , '#');
}
//寻找存在该非终结符的产生式
for(int j=0;j<n;j++){
if(gramOldSet[j].formula.find(nont)>=3){
//当它为产生式结尾
if(gramOldSet[j].formula.find(nont) == gramOldSet[j].formula.size()-1) {
//非终结符是否求过follow集
if(flag[is_non_ter(gramOldSet[j].formula[0])]==1) {
Follow(gramOldSet[j].formula[0]);
}
if(flag[is_non_ter(gramOldSet[j].formula[0])]==0) {
for(int k=0;k<followSET[is_non_ter(gramOldSet[j].formula[0])].size(); k++){
addF(followSET[is_non_ter(nont)], followSET[is_non_ter(gramOldSet[j].formula[0])][k]);
}
}
}
//当它不是产生式结尾
else if(gramOldSet[j].formula.find(nont) < gramOldSet[j].formula.size()-1){
pfml = &gramOldSet[j].formula[ gramOldSet[j].formula.find(nont) ]; //该非终结符在队中的位置指针
bool is_kong=true;
int k=0;
for( k=gramOldSet[j].formula.find(nont)+1; k < gramOldSet[j].formula.size();k++){
//终结符,添加本身
if(is_terSymbol(gramOldSet[j].formula[k])>=0){
addF(followSET[is_non_ter(nont)], gramOldSet[j].formula[k]);
break;
}
//非终结符,添加first集
for(int p=0; p<firstSET[is_non_ter(gramOldSet[j].formula[k])].size(); p++){
if(firstSET[is_non_ter(gramOldSet[j].formula[k])][p] == '$') continue;
addF(followSET[is_non_ter(nont)], firstSET[is_non_ter(gramOldSet[j].formula[k])][p]);
}
if(!forkong(gramOldSet[j].formula[k])){
is_kong=false;
break;
}
}
//能推出空字符todo
if (is_kong){
// if(flag[is_non_ter(pfml[1])] == 1) Follow(pfml[1]);
if(flag[is_non_ter(pfml[1])] == 0) {
for(int m=0;m<followSET[is_non_ter(gramOldSet[j].formula[0])].size(); m++){
addF(followSET[is_non_ter(nont)], followSET[is_non_ter(gramOldSet[j].formula[0])][m]);
}
}
}
}
}
else{
continue;
}
}
}
else{
continue;
}
}
flag[is_non_ter(nont)]=0;
}
//构造预测分析表
void Table(){
for(int i=0;i<non_ter.size();i++){
for(int j=0;j<terSymbol.size();j++){
M[i][j]=-1;
if(firstSET[i].find(terSymbol[j])!=-1 || followSET[i].find(terSymbol[j])!=-1){
//k为当前产生式编号
for(int k=0;k<n;k++){
if(gramOldSet[k].formula[0]==non_ter[i]){
bool is_kong = true;
for(int p=3;p<gramOldSet[k].formula.size();p++){
//为终结符
if(is_terSymbol(gramOldSet[k].formula[p])>=0 && gramOldSet[k].formula[p]==terSymbol[j]){
M[i][j]=k;
is_kong=false;
break;
}
//当前非终结符first集中有该j
else if (firstSET[is_non_ter(gramOldSet[k].formula[p])].find(terSymbol[j])!=-1){
M[i][j]=k;
break;
}
//阿尔法不能推出空
if(!forkong(gramOldSet[k].formula[p])&&gramOldSet[k].formula[p]!='$'){
is_kong=false;
break;
}
}
if(is_kong){
if(followSET[i].find(terSymbol[j])!=-1){
M[i][j]=k;
}
}
}
}
}
}
}
}
//总控程序
bool Control(){
stack<char> S;
string str;
char x;
S.push('#');
S.push(gramOldSet[0].formula[0]);
bool flag=true;
cin>>str;
// char *a=&str[0];
string::iterator a = str.begin();
print(S,str);
cout<<endl;
while(flag){
// x = S.top();
//x==a=='#'时
if(S.top()=='#'){
if(S.top()==*a){
flag=false;
}else{
cout<<"error"<<endl;
return false;
}
}
//栈顶为终结符
else if(terSymbol.find(S.top())!=-1){
if(S.top()==*a){
S.pop();
a=str.erase(a);
print(S,str);
cout<<endl;
}else{
cout<<"error"<<endl;
return false;
}
}
//栈顶为非终结符
else if(non_ter.find(S.top())!=-1){
int num=M[is_non_ter(S.top())][is_terSymbol(*a)];
S.pop();
if(num>=0){
for(int i=gramOldSet[num].formula.size()-1;i>=3;i--){
if(gramOldSet[num].formula[i]=='$') break;
S.push(gramOldSet[num].formula[i]);
}
}
print(S,str);
cout<< gramOldSet[num].formula <<endl;
}else{
return false;
}
}
}
//向first或follow集中添加
int addF(string &s, char c){
if(s.find(c)!=-1) return 0;
else{
s.push_back(c);
return 1;
}
}
int is_terSymbol(char c){
if(terSymbol.find(c)>=0) return terSymbol.find(c);
else return -1;
}
int is_non_ter(char c){
if(non_ter.find(c)>=0) return non_ter.find(c);
else return -1;
}
//能退出空返回true,不能返回false
bool forkong(char c){
if(is_terSymbol(c)>=0) return false;
int s=is_non_ter(c);
for(int i=0; i<n; i++){
if(c==gramOldSet[i].formula[0]){
if(gramOldSet[i].formula[3]=='$' && gramOldSet[i].formula.size()==4) return true;
else if (is_non_ter(gramOldSet[i].formula[3])>=0){
return forkong(gramOldSet[i].formula[3]); //递归查看是否为空
}
}
}
return false;
}
//格式化输出
void print(stack<char> S, string str){
static int i=0;
cout.width(5);
cout<< left << i ;
i++;
string sta;
for(int j=S.size()-1;j>=0;j--){
sta.insert(sta.begin(),S.top());
S.pop();
}
cout.width(10);
cout<< left << sta ;
cout.width(10);
cout<< right << str <<" ";
}
测试数据:
ASDFG
i+*()
8
A->DS
S->+DS
S->$
D->GF
F->*GF
F->$
G->(A)
G->i
i*i+i#
输出依次为按输入非终结符顺序的First集和Follow集、预测分析表、分析过程与结果。