您的位置:首页 > 编程语言 > C语言/C++

语法分析表产生器的代码之三:自定义类的实现函数文件implement_syntax.cpp

2005-06-14 20:17 821 查看
#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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  table c++ c null file excel
相关文章推荐