#include"myclass.h"
#include<iostream>
#include<fstream>
#include<iomanip>
using namespace std;
static endnotation=0;//标记终结符(如$)
static nontermCountM=0;//标记空产生式(如[)
production::production()
{
left = -1;
length = 0;
for(int i=0;i<100;i++)
right[i] = -1;
}
void production::setRight(int i)
{
right[length] = i;
length++;
}
//class syntaxG/
syntaxG::syntaxG()
{
stateCount = 0;
//存入终结符
fstream file;
file.open("dd.txt",3);
if(!file)
{
cout<<"文件打开失败!"<<endl;
exit(-1);
}
//读入终结符
termCount = 0;
char ch=file.peek(),charray[500];
for(int t=0;ch!='#';t++)
{
file>>charray;
file.get(&ch,2,EOF);
signs[t] = charray;
termCount++;
ch=file.peek();
}
file>>charray;//去掉分隔符###############
ch=file.peek();
//读入非终结符
nontermCount=termCount;
for(t=termCount;ch!='#';t++)
{
file>>charray;
file.get(&ch,2,EOF);
if(charray[1]!='/0')//替换较长的非终结符
{
strcpy(signs[t].notation.replaced,charray);
signs[t].notation.charray[0] = (char)(128+replacecount);
signs[t].notation.charray[1] = '/0';
replacecount++;
nontermCount++;
ch = file.peek();
continue;
}
signs[t] = charray;
nontermCount++;
ch=file.peek();
}
endnotation = termCount;
nontermCountM = nontermCount;
file>>charray;//去掉分隔符###############
ch=file.peek();
//读入产生式
prodCount = 0;
int index_charray=0;
for(t=0;ch!='#';t++)
{
file>>ch;
if(ch == '#')
break;
while(true)
{
charray[index_charray] = ch;
charray[index_charray+1]='/0';
index_charray++;
ch=file.peek();
if(ch==' '||ch=='-'||(int)ch==9)
break;
file>>ch;
}
for(int h=termCount;h<nontermCount;h++)//为左部寻找非终结符
{
if(signs[h].notation==charray)
break;
}
/*file.get(&ch,2,EOF);
file.get(&ch,2,EOF);
ch=file.peek();*/
while(ch==' '||ch=='-'||ch=='>'||(int)ch==9)//清除中间
{
file.get(&ch,2,EOF);
ch = file.peek();
}
index_charray=0;
if(ch==signs[nontermCount-1].notation[0])//如果是空产生式
{
file.get(&ch,2,EOF);
signs[h].theEmptyProductionID = 1;
productions[prodCount].left = h;
productions[prodCount].setRight(nontermCount-1);
prodCount++;
index_charray=0;
continue;
}
while((int)ch!=10 )//读取右部
{
while(ch==' '||(int)ch==9)
{
file.get(&ch,2,EOF);
ch=file.peek();
}
file.get(&ch,2,EOF);
charray[index_charray] = ch;
charray[index_charray+1] = '/0';
for(int p=0;p<nontermCount;p++)//查询所有的终结符与非终结符,看看能不能找到匹配的
{
if(signs[p].notation==charray)
break;
}
if(p!=nontermCount)//如果找到匹配的符号,则:
{
productions[prodCount].left = h;
productions[prodCount].setRight(p);
index_charray=0;
}
else
{
index_charray++;
}
ch = file.peek();
}
prodCount++;
}
//计算各个终结符与非终结符的first集,两次循环保证求出完整的first集
for(int k=0;k<nontermCount;k++)
{
for(int i=0;i<nontermCount;i++)
constructFirstfor(signs[i],i);
}
//构造各个非终结符的follow集
signs[termCount].addfollow(termCount-1);//先把$放到开始符号的follow集中
constructFollowFor();
}
void syntaxG::constructFollowFor()
{
int k,j,tmp,t;
bool FirstCollectionofRightPartHasEmptyProduction=1,AssistFlag=0;
//遍历所有产生式,迭代元为productions[i]
for(int loop=0;loop<prodCount;loop++)
{
for(int i=0;i<prodCount;i++)
{
k=0;//k用来跟踪产生式的右部元素
t=k+1;//t用来跟踪这个右部元素后面的元素,从k的下一个元素k+1开始
while(productions[i].right[k] != -1)//遍历产生式的所有右部元素,迭代元为productions[i].right[k],求它的follow集
{
FirstCollectionofRightPartHasEmptyProduction=1;//默认情况下标记k的右部所有元素均能推出空符号
AssistFlag=0;
//如果这个元素是终结符或者是空产生式的话,跳过
if(productions[i].right[k] < termCount ||productions[i].right[k] == nontermCount-1 )
{
k++;
t=k+1;
continue;
}
if(productions[i].right[k+1] != -1)//如果是A->aBb形式的,即k后面还有元素(标记为t),则:
{
while(productions[i].right[t] != -1)
{
j=0;//j用来跟踪这个后续元素t的first集元素
tmp = signs[productions[i].right[t]].first[j];
//把后续元素t的first集所有元素加入到前面这个元素k的follow集中(除空符号外)
while(tmp != -1)
{
if(tmp == nontermCount-1)//如果元素t的first集里有空符号,则标记一下
{
AssistFlag = 1;
}
signs[productions[i].right[k]].addfollow(tmp);
j++;
tmp = signs[productions[i].right[t]].first[j];
}
if(AssistFlag==0)//如果元素t的first集中没有空符号,则对于元素k,就不需要再看t后面的元素的first了
{
FirstCollectionofRightPartHasEmptyProduction = 0;
break;
}
else//如果有,则继续遍历元素k后面的元素t+1,把它的first集也加进来
{
AssistFlag = 0;
t++;
}
}
if(FirstCollectionofRightPartHasEmptyProduction == 1)//对于这个产生式A->aBb来说,串b能推出空符号
//(注意这种情况要求串b中的所有元素的first集中均含有空符号)
{
//则把产生式的左部元素的follow集都加到元素k的follow中
int anotherj=0;
int anothertmp=signs[productions[i].left].follow[anotherj];
while(anothertmp != -1)
{
signs[productions[i].right[k]].addfollow(anothertmp);
anotherj++;
anothertmp = signs[productions[i].left].follow[anotherj];
}
}
}
else//如果是A->aB形式的,则:
{
int AndOnejMore=0;
int AndOnetmpMore= signs[productions[i].left].follow[AndOnejMore];
while(AndOnetmpMore != -1)
{
signs[productions[i].right[k]].addfollow(AndOnetmpMore);
AndOnejMore++;
AndOnetmpMore= signs[productions[i].left].follow[AndOnejMore];
}
}
k++;
t=k+1;
}
}
}
}
//求终结符或非终结符sn的first集(注意:sn只是符号,而i是其在signs数组里的索引)
void syntaxG::constructFirstfor(sign &sn,int i)
{
if(i<termCount)
sn.first[0] = i;
else
{
for(int j=0;j<prodCount;j++)//遍历所有产生式
{
if(productions[j].left==i)//如果找到本“非终结符”的产生式,则:
{
if(productions[j].right[0] == nontermCount-1)//如果是空产生式的话,则将之加入此集合
{
sn.addfirst(nontermCount-1);
}
else//不是空产生式,则递归
{
//如果产生式的右部第一个字符就是它自己(左递归),则跳出
if(i==productions[j].right[0])
{
continue;
}
else //如果产生式的右部第一个字符是终结符
if(productions[j].right[0]>=0 && productions[j].right[0]<termCount)
{
sn.addfirst(productions[j].right[0]);
}
else
{
int c=0; //c用来标记产生式右部的第几个非终结符
//当然,必须前面是非终结符且有空产生式时c才能向右移动
//如果产生式的右部第一个字符是非终结符
do{
if(productions[j].right[c]>=termCount && productions[j].right[c]<nontermCount)
{
int k=0;
//tmp依次遍历这个最右字符的first集中的元素并加入,直到-1为止
for(int tmp=signs[productions[j].right[c]].first[k];tmp!=-1;k++)
{
sn.addfirst(tmp);
tmp=signs[productions[j].right[c]].first[k];
}
}
c++;
}while(signs[c-1].theEmptyProductionID!=-1);
}
}
}
}
}
}
void syntaxG::stateEmerge()
{
states[0].itemCount ++;
states[0].items[0].productionID = 0;
states[0].items[0].pointPosition = 0;//初始化第一个状态states[0]:S=.E
stateCount++;
closure(states[0]);
bool ThereIsMoreStates = true;
while(ThereIsMoreStates)//如果为false,说明全部状态已经算出
{
ThereIsMoreStates = false;
for(int i=0;i<stateCount;i++)
{
for(int j=termCount;j<nontermCount-1;j++)//以非终结符作为下一个输入符X,求goto(state,X)
{
state * tmp = gotofunc(states[i],j);
if(tmp)//如果这个非终结符能生成一个状态
{
if(!isThisStateAlreadyGotten(*tmp))//判断一下在不在状态集合中,不是的话加进去
{
states[stateCount] = *tmp;
stateCount ++;
ThereIsMoreStates = true;
}
}
}
for(j=0;j<termCount;j++)//以终结符作为下一个输入符X,求goto(state,X)
{
state * tmp = gotofunc(states[i],j);
if(tmp)//如果这个终结符能生成一个状态
{
if(!isThisStateAlreadyGotten(*tmp))//判断一下在不在状态集合中,不是的话加进去
{
states[stateCount] = *tmp;
stateCount ++;
ThereIsMoreStates = true;
}
}
}
}
}
}
int syntaxG::isThisStateAlreadyGotten(const state &s)
{
for(int i=0;i<stateCount;i++)
{
if(states[i] == s)
return i;
}
return 0;//还没有这个状态,这是个新状态
}
void syntaxG::closure(state& s)
{
int itmp;
for(int i=0;i<s.itemCount;i++)
{
itmp = productions[s.items[i].productionID].right[s.items[i].pointPosition];
if(itmp>=termCount && itmp<nontermCount)//如果项目的"点"后面的字符是一个非终结符
{
for(int j=0;j<prodCount;j++)//在所有产生式中查找
{
if(productions[j].left == itmp)//如果找到左部是itemp的产生式j
{
for(int k=0;k<s.itemCount;k++)//再确定这个产生式是否已经在项目集中
{
if( s.items[k].productionID == j && s.items[k].pointPosition == 0)//如果都相等,则这个产生式已存在
break;
}
if(k == s.itemCount)//如果项目集中没有,则添加此项目进去
{
if(productions[j].right[0]==nontermCount-1)
{
s.items[s.itemCount].productionID = j;
s.items[s.itemCount].pointPosition = 1;
s.itemCount ++;
}
else
{
s.items[s.itemCount].productionID = j;
s.items[s.itemCount].pointPosition = 0;
s.itemCount ++;
}
}
}
}
}
}
//cout<<"dd";//调试语句
}
state* syntaxG::gotofunc(const state& s,int itmp)
{
state *tmp=NULL;
for(int i=0;i<s.itemCount;i++)//寻找s中"点"后面是itmp所代表符号的产生式
{
if(tmp == NULL)//如果至今还未找到,进这里
{
if(itmp == productions[s.items[i].productionID].right[s.items[i].pointPosition])
{
tmp = new state();
tmp->itemCount ++;
tmp->items[0].productionID = s.items[i].productionID;
tmp->items[0].pointPosition = s.items[i].pointPosition + 1;
closure(*tmp);
}
}
else//如果已经找到,说明新状态new好了,进这里
{
if(itmp == productions[s.items[i].productionID].right[s.items[i].pointPosition])
{
tmp->items[tmp->itemCount].productionID = s.items[i].productionID;
tmp->items[tmp->itemCount].pointPosition = s.items[i].pointPosition + 1;
tmp->itemCount ++;
closure(*tmp);
}
}
}
return tmp;
}
void syntaxG::tableConstruction()
{
state * tmp=NULL;
for(int i=0;i<stateCount;i++)//对每一个状态进行计算
{
for(int j=0;j<termCount;j++)//对每一个终结符进行迭代
{
tmp = gotofunc(states[i],j);//求goto(state,X)
if(tmp)//如果为真则找到,则标记相应表项
{
table[i][j].ch = 's';
table[i][j].number = isThisStateAlreadyGotten(*tmp);
}
}
for(j=0;j<states[i].itemCount;j++)
{
//如果这个项目类似于A->a.这种形式,则把follow(A)中的所有a置为归约
//注意:对每个状态集合,这样的产生式只可能有一个,因为这是等价于有穷确定自动机的
if(productions[states[i].items[j].productionID].length == states[i].items[j].pointPosition)
{
if(productions[states[i].items[j].productionID].left == termCount)//接受状态S->E
{
table[i][termCount-1].ch = 'a';
table[i][termCount-1].number = 0;
continue;
}
int tmpleft=productions[states[i].items[j].productionID].left;
int k=0;
while(signs[tmpleft].follow[k] != -1)//取左部元素的follow集元素
{
if(table[i][signs[tmpleft].follow[k]].ch == 's')
{
table[i][signs[tmpleft].follow[k]].ch = 'o';//移进归约冲突
table[i][signs[tmpleft].follow[k]].number = states[i].items[j].productionID+table[i][signs[tmpleft].follow[k]].number*100;
}
else
if(table[i][signs[tmpleft].follow[k]].ch == 'r')
{
table[i][signs[tmpleft].follow[k]].ch = 'p';//归约归约冲突
table[i][signs[tmpleft].follow[k]].number = states[i].items[j].productionID+table[i][signs[tmpleft].follow[k]].number*100;
}
else
{
table[i][signs[tmpleft].follow[k]].ch = 'r';
table[i][signs[tmpleft].follow[k]].number = states[i].items[j].productionID;
}
k++;
}
}
}
for(j=termCount;j<nontermCount;j++)//对每一个非终结符进行迭代
{
tmp = gotofunc(states[i],j);//求goto(state,X)
if(tmp)//如果为真则找到,则标记相应表项
{
table[i][j].ch = '/0';
table[i][j].number = isThisStateAlreadyGotten(*tmp);
}
}
}
}
void syntaxG::printG()
{
fstream d;
d.open("ee.txt",2);
cout<<endl;
cout<<"the grammer:"<<endl;
for(int i=0; i<prodCount;i++)//输出文法产生式
{
cout<<signs[productions[i].left].notation<<"->";
for(int h=0;h<productions[i].length;h++)
cout<<signs[productions[i].right[h]].notation<<" ";
cout<<endl;
}
cout<<"*****************************************"<<endl;
cout<<"finished!"<<endl;
d<<"*****************************************"<<endl;
for(i=0;i<stateCount;i++)//输出状态集族
{
d<<"state"<<i<<": "<<endl;
for(int v=0;v<states[i].itemCount;v++)
{
d<<signs[productions[states[i].items[v].productionID].left].notation<<"->";
for(int w=0;w<productions[states[i].items[v].productionID].length;w++)
{
if(w==states[i].items[v].pointPosition)
{
d<<".";
}
d<<signs[productions[states[i].items[v].productionID].right[w]].notation<<" ";
}
if(productions[states[i].items[v].productionID].length==states[i].items[v].pointPosition)
d<<".";
d<<endl;
}
d<<endl;
}
d<<endl;
for(int c=0;c<nontermCount;c++)//输出first集
{
int i=0;
d<<"First collection of /""<<signs[c].notation<<"/" is :";
while(signs[c].first[i]!=-1)
{
d<<signs[signs[c].first[i]].notation<<" ";
i++;
}
d<<endl;
}
d<<endl;
for(c=termCount;c<nontermCount;c++)//输出follow集
{
int i=0;
d<<"Follow collection of /""<<signs[c].notation<<"/" is :";
while(signs[c].follow[i]!=-1)
{
d<<signs[signs[c].follow[i]].notation<<" ";
i++;
}
d<<endl;
}
for(c=0;c<nontermCount;c++)
{
d<<c+1<<":"<<signs[c].notation<<endl;
}
for(c=0;c<nontermCount-1;c++)
{
d<<"/t"<<c+1;
}
cout<<endl;
d<<endl;
for(int j=0;j<stateCount;j++)//输出构造好的分析表
{
d<<"state"<<j<<"/t";
for(int k=0;k<nontermCount-1;k++)
{
d<<table[j][k].ch<<table[j][k].number<<"/t";
}
d<<endl;
}
fstream additionalfile;
additionalfile.open("能直接拷入Excel的分析表.txt",2);
for(c=0;c<nontermCount-1;c++)
{
additionalfile<<"/t"<<c+1;
}
int tmpp;
additionalfile<<endl;
for(j=0;j<stateCount;j++)//输出构造好的分析表
{
additionalfile<<j<<"/t";
for(int k=0;k<nontermCount-1;k++)
{
if(table[j][k].ch=='r')
tmpp = -1*(table[j][k].number);
else
if(table[j][k].ch=='o')
tmpp = table[j][k].number + 1000000;
else
if(table[j][k].ch=='p')
tmpp = table[j][k].number + 2000000;
else
if(table[j][k].ch=='a')
tmpp=table[j][k].number+3000000;
else
tmpp = table[j][k].number;
additionalfile<<tmpp<<"/t";
}
additionalfile<<endl;
}
}
//class item
item::item()
{
productionID = -1;
pointPosition = 0;
}
bool item::operator ==(const item& t)
{
if(t.pointPosition != this->pointPosition || t.productionID != this->productionID)
return false;
return true;
}
//class state///
state::state()
{
itemCount = 0;
}
void state::operator =(const state& s)
{
this->itemCount = s.itemCount;
for(int i=0;i<s.itemCount;i++)
{
this->items[i].productionID = s.items[i].productionID;
this->items[i].pointPosition = s.items[i].pointPosition;
}
}
bool state::operator ==(const state& s)
{
if(this->itemCount != s.itemCount)
return false;
for(int i=0;i<s.itemCount;i++)
{
if(this->items[i] == s.items[i])
continue;
else
return false;
}
return true;//即参与比较的两个状态是一样的
}
//class tableItem///
tableItem::tableItem()
{
ch = '/0';
number = 0;
}
//class sign
sign::sign()
{
notation[0] = '/0';
theEmptyProductionID = -1;
for(int i=0;i<100;i++)
{
first[i] = -1;
follow[i] = -1;
}
}
void sign::operator =(char arr[])
{
notation=arr;
}
void sign::addfirst(int number)
{
int i=0;
while(first[i] != -1)
{
if(first[i]==number)
return;
i++;
}
first[i]=number;
}
void sign::addfollow(int number)
{
int i=0;
if(number==endnotation || number==nontermCountM-1)//空产生式不能加到follow集中
return;
while(follow[i] != -1)
{
if(follow[i]==number)
return;
i++;
}
follow[i]=number;
}
//class notationclass///
notationclass::notationclass()
{
charray[0] = '/0';
replaced[0] = '/0';
}
ostream& operator<<(ostream& o,const notationclass& n)
{
if((int)n.charray[0] < 128 && ((int)n.charray[0] > 0))
o<<n.charray;
else
o<<n.replaced;
return o;
}
void notationclass::operator =(char ch[])
{
strcpy(charray,ch);
}
char& notationclass::operator [](int i)
{
return charray[i];
}
int notationclass::operator ==(char ch[])
{
if(charray[0]>0 && charray[0]<128)
return !strcmp(ch,charray);
else
return !strcmp(ch,replaced);
}