回 帖 发 新 帖 刷新版面

主题:C++的词法和语法分析

各位大虾啊,救救急好吗?本人将不胜感激!
我急着交一个关于C++的词法和语法分析作业,
那个编译作业是这个样子的:

  
对C++进行词法和语法分析。
要求:
   词法分析部分写出相应的正规集、正规式、NFA、DFA   
   写出语法分析所采用的方法和完成的语法分析功能     
   编写出响应的编译程序     
   写出完整的课程设计报告

说明:课程设计报告包括的基本内容有:
一、课程设计题目
二、课程设计的目的
三、课程设计的基本内容和实现功能介绍
四、词法分析:包括系统的词法规则,相应的正规集、正规式、NFA、DFA
五、语法分析:包括语法规则,分析所采用的技术和算法

回复列表 (共15个回复)

沙发

不是吧
你大几了
要搞这个

板凳

前些日子写的LL(1)语法分析器。可以构造非递归的FIRST和FOLLOW集还有预测分析表。希望对你有帮助。好运。

3 楼


// Using STL
// C++ forever ...

# include <iostream>
# include <stdlib.h>
# include <list>
# include <string>

using namespace std;

class elem
{
public:
string name;
list<string> first; // first set
list<string> follow; // follow set
};


const int MAXSIZE = 16; // maxium terminal symbol and maxium no-terminal symbol
const int MAXLINE = 32; // maxium lines of the input grammer
extern int lineno; // record how many lines
extern int colineno;
const string ee = "e"; // the empty string
extern bool isLL1Grammer; // judge whether a given grammer is a LL(1) grammer
extern elem symbol[MAXSIZE]; // to hold first and follow set for each symbol
extern string LL1_table[MAXSIZE][MAXSIZE]; // only for showing non-empty elements
extern list<string> production[MAXLINE]; // for getting grammer from standard input stream
extern list<string> coProduction[MAXLINE];
extern list<string> VN; // hold no-terminal symbols
extern list<string> VT; // hold terminal symbols
extern list<string> First;
extern list<string> Follow;

/* ---------------- function declaration --------------------- */
void getGrammer();
void getCoGrammer();
bool isLeftRecursion();
void emitLeftRecursion(); // for emiting later...
void print(list<string>& ); // to print structure
void removeDup(list<string>& ); // to remove duplicate
void getVN(); // get set of no-terminals
void getVT(); // get set of terminals
bool isIn(string,list<string>&); // judge if a given string is in a list
void listToString(string& ,list<string> ); // copy list to a string
void noRightReserve(); // for printing message
void getName(); // get the name of symbol
void buildFirst(); // build FIRST set
void printFirst(); // print FIRST of each no-terminals
void buildFollow(); // build FOLLOW set
void printFollow(); // print FOLLOW of each non-terminals
void initTable(); // inisialize the LL1 table
void buildTable(); // build LL1 table ( using some algorithm )
void printTable(); // print the LL(1) table
/* ---------------------------------------------------------- */

4 楼

# include "global.h"

using namespace std;

int main()
{
   //////////// get grammer for standard stream
   getGrammer();
   getCoGrammer();
   ////////  emit_leftRecursion.cpp ////////////////
   if(isLeftRecursion()){
    cout << "***********************************" << endl;
   cout << "This version cannot deal with left recursion grammer." <<endl;
   cout << "The version will coming after handing in my Java " << endl;
   cout << "homework :( .   @ Math Frog " << endl;
    cout << "***********************************" << endl;
   }
   else{
   //////////// getVnVt.cpp ////////////////////////
   getVN();
   getVT();
   /////////////////////////////////////////////////
   /// constructFirstAndFollow.cpp ////////////////
   buildFirst();
   printFirst();
   buildFollow();
   printFollow();
   ////////////////////////////////////////////////
   //////////////// bottomtoUpAnylysis.cpp ////////
    initTable();
    buildTable();
    printTable();
   }
   /////////////// tools.cpp /////////////////////
   system("PAUSE");
   noRightReserve();
   system("PAUSE");     
  return 0;
}

5 楼

# include "global.h"

/*-----------------------------------------
  To get grammer from the standard input
   stream.
    avoid file processing :P  
------------------------------------------*/

string choice; // for user's decision

int lineno = 0;

list<string> production[MAXLINE];

void showMessage()
{
  cout << " LL(1) parsing machine @ Math Frog && FLower @ " << endl;
  cout << endl;
  cout << " ** Please input the grammer you want to process ** \n";
  cout << "\n ** REMIND : Just type a space after entering a symbol **";
  cout << "\n ** press # to end inputing production **";
  cout << "\n ** press $ to end inputing grammer **" << endl;
  cout << "***********************************" << endl;
  }

void getGrammer()
{
while(true){
  showMessage();
  string tmp; // holding input string temporily  
  for(;lineno < MAXLINE;){
     cout << "line " << lineno << ": ";
     cin >> tmp;
     while(tmp != "#" && tmp != "$"){
     production[lineno].push_back(tmp);
     cin >> tmp;
     }
  if(tmp == "$") break; // end inputing grammer
  lineno++;
   }   
   cout << "***********************************" << endl;
  cout << endl;
for(int j = 0;j < lineno;j++)
  print(production[j]);
  cout << endl;
   cout << "***********************************" << endl;
  cout << endl;
  cout << "\nIs the grammer you want to anlysis ? " << endl;
  cout << endl;
  cout << "(Type Y for yes and N for no)" << endl;  
  cin >> choice;
  if(choice == "Y")
   break;
  for(int i = 0;i < lineno;i++) // everything just begins
   production[i].erase(production[i].begin(),production[i].end());
   lineno = 0;
}
}


void getCoGrammer()
{
list<string> hold;
for(int line = 0;line < lineno;line++){
  list<string>::iterator iter = production[line].begin();
   iter++; // to the ->
   iter++; // to the first on the right of the production
  while(iter != production[line].end()){
   hold.push_back(production[line].front());
     hold.push_back("->");
     if(iter == --production[line].end())
       hold.push_back(*iter);
     else{
       while(*iter != "|" && iter != production[line].end()){
         hold.push_back(*iter);
         if(iter == --production[line].end()) break;
         iter++;
       }
     }
     coProduction[colineno++] = hold; // just use the overloaded =
     hold.erase(hold.begin(),hold.end()); // make hold empty list
     iter++;
   }
  }
}

6 楼

# include "global.h"

// import
list<string> VN;
list<string> VT;

void getVN()
{
for(int i = 0;i < lineno;i++)
   VN.push_back(*(production[i].begin()));
  
   if(!VN.empty()){
    removeDup(VN); // remove duplicated elements
    cout << "***********************************" << endl;
    cout << "** The set of non-ternminal symbols of this grammer is as follow ** \n";
    cout << "***********************************" << endl;
    cout << endl;
   print(VN);
   cout << endl;
   cout << "***********************************" << endl;
   
   }
}

void getVT()
{  
   string tmp;
   list<string>::iterator point,hold;
   for(int i = 0;i < lineno;i++){
      point = production[i].begin();
       while(*point != "->")
          point++;
       hold = ++point;
      while(hold != production[i].end()){
        tmp = *hold;
        if(tmp != "|" && !isIn(tmp,VN) && tmp != "e")
          VT.push_back(*hold); // push to the set of VT
          hold++;
     }
    }
   if(!VT.empty()){
   removeDup(VT);
   cout << "***********************************" << endl;
   cout << "** The set of terminal symbols of this grammer is as follow ** \n";
   cout << "***********************************" << endl;
   cout << endl;
   print(VT);
   cout << endl;
   cout << "***********************************" << endl;
   cout << endl;
   }
}
  

7 楼

/*
Some tool functions
using very simple linear algorithm
*/
# include "global.h"

void print(list<string>& l)
{
  list<string>::iterator iter = l.begin();
  while(iter != l.end())
   cout << *iter++ << " ";
   cout << endl;
}

void removeDup(list<string>& l)
{
  string hold;
list<string>::iterator sIter,pIter;
  pIter = l.begin();
while(pIter != l.end()){
  hold = *pIter;
  sIter = pIter;
  sIter++;
  while(sIter != l.end())
   if(*sIter == hold)
     l.erase(sIter++);
   else sIter++;
   pIter++;
}
}

bool isIn(string target,list<string>& s) // to decide whether a symbol is a terminal symbol or
                                          // non-terminal symbol
{   // or for something judgement in later procession
   // sequencial search , only for small instance :)
    // I am not quite sophlicated in algorithm
   list<string>::iterator iter = s.begin();
while(iter != s.end()){
   if(*iter == target)
   return true;
   iter++;
  }      
  return false;
}

void listToString(string& s,list<string> l)
{
// the string has fixed ...
  list<string>::iterator iter;
  for(iter = l.begin();iter != l.end();iter++){
      s.append(*iter); // append to the string
      s.append(" ");
      }
}
void noRightReserve()
{
// holding for later usage
   cout << "***********************************" << endl;
   cout << "* LL(1) parsing version 0.5 " << endl;
   cout << "***********************************" << endl;
  cout << "\n\n\n*Me aNd FlOwEr ArE LiViG HaPPiLY Now\n";
  cout << "* AnD HoW MuCh We LoVe ThIs WoRlD\n";
  cout << "* Mathematics Worm Association" << endl;
  cout << "           * Math Frog  6.8.2005 " << endl;
  cout << "                @ No Right Reserve" << endl;
  cout << "***********************************" << endl;
  }

8 楼

/*
This part becomes simple after FIRST set and FOLLOW set
are constructed
   finished on  6.8
        Math Frog
*/
# include "global.h"

string LL1_table[MAXSIZE][MAXSIZE]; // import
list<string> tmpfirst; // for holding first set of alpha
bool isLL1Grammer;
void initTable() // initialize the LL1_table
{
   list<string>::iterator iter;
   LL1_table[0][0] = "M[VN,VT]";
   int row = 1,col = 1;
  
    for(iter = VN.begin();iter != VN.end();iter++)
         LL1_table[row++][0] = *iter;
    for(iter = VT.begin();iter != VT.end();iter++)
        LL1_table[0][col++] = *iter;
        LL1_table[0][col] = "$" ; // make $ a terminal
  // for decide the position
}
void buildTable()
{
list<string>::iterator iter,it,copy;
string hold;
int save,pos;
int row,col; // for adding element to the table ...
  for(int line = 0;line < colineno;line++){
     // compute A->X1X2...Xn
      iter = coProduction[line].begin();
      hold = *iter;// save for searching
    for(row = 1;row <= VN.size();row++)
       if(LL1_table[row][0] == hold) break; // find the current non-terminal in the table
    for(int i = 0;i < VN.size();i++)
       if(hold == symbol[i].name)
          {pos = i;break;}  // in the symbol ...
      iter++;iter++; // to the right
      it = iter; // begin finding
  ////computing the first set of alpha ///////////////
   while(it != coProduction[line].end()){
      if(isIn(*it,VT) || *it == ee) // the current symbol is a terminal
        {tmpfirst.push_back(*it);break;} // because terminal's first set has no e in
                                         // so the computation ends or in the last
       else{ // is not a terminal
          for(int i = 0;i < VN.size();i++)
             if(*it == symbol[i].name)
                 {save = i;break;}
       for(copy = symbol[save].first.begin();copy != symbol[save].first.end();copy++)
           if(!isIn(*copy,tmpfirst))
             tmpfirst.push_back(*copy); // to copy
        }
        if(!isIn(ee,tmpfirst)) break; // symbol[save]'s first has no e ,to end
                                        // the computation...
        it++;
      }
     ///////////////////////////////////////////////
     // scan alpha's first set...
   for(it = tmpfirst.begin();it != tmpfirst.end();it++)
     if(isIn(*it,VT)){ // the current symbol is a terminal
      // then add A->alpha to LL1_table[A][alpha]
      // decide the position
       for(col = 1;col <= VT.size() + 1;col++)  
          if(*it == LL1_table[0][col]) break;
        listToString(LL1_table[row][col],coProduction[line]);
      }
      if(isIn(ee,tmpfirst)){ // if the empty string is in the FIRST(X1X2..Xn)
    for(it = symbol[pos].follow.begin();it != symbol[pos].follow.end();it++)
           if(isIn(*it,VT) || *it == "$"){
             if(*it == "$")
         listToString(LL1_table[row][VT.size() + 1],coProduction[line]);
           else{
             for(col = 1;col <= VT.size() + 1;col++)
             if(*it == LL1_table[0][col]) break;
              listToString(LL1_table[row][col],coProduction[line]);
             }
           }
         }
      tmpfirst.erase(tmpfirst.begin(),tmpfirst.end());
     }
   for(row = 1;row <= VN.size();row++)
     for(col = 1;col <= VT.size() + 1;col++)  
       if(LL1_table[row][col].empty())
         LL1_table[row][col] = "Error";
   }
void printTable()
{
  int row ,col;
   cout << "***********************************" << endl;
   cout << "** The LL(1) Table is as follow **" << endl;
    cout << "***********************************" << endl;
  for(row = 1;row <= VN.size();row++){
    for(col = 1;col <= VT.size() + 1;col++){
  cout << " |**  M[ " << LL1_table[row][0] << ", " << LL1_table[0][col] << " ] = ";
  cout << LL1_table[row][col] << "\t";
  cout << "   **|" << endl;
}
  }
     cout << "***********************************" << endl;
}

9 楼

/*
  To construct FIRST and FOLLOW set
  This part plays a key role up-bottom anlysis.
  And it is the most difficult part to code.
    start on 6.5
   plan finish on 6.7  
                       by Math Frog
  */
# include "global.h"

// import global variable

elem symbol[MAXSIZE];

list<string> coProduction[MAXLINE];

list<string> cofirst; // to hold the tempory first set
                      // for the production list X1X2...Xn
const int CNT = 2;// scan times
const int _CNT = 3;
int colineno = 0; // lineno of the new grammer

void getName()
{
   int i = 0;
   list<string>::iterator iter = VN.begin();
   while(iter != VN.end())
   symbol[i++].name = *iter++; // get name of each symbol
}

/*
** build first set for each non-terminals **
   finished on 6.6    Math Frog
*/
void buildFirst()
{
string hold1,hold2,hold3;
list<string> hold; // hold for getting separete production
int save1,save2; // save position  
int cnt = 0;
int mark;
bool flag;
list<string>::iterator iter,tmp;
getName();
////////////////// first scan ////////////////////////
///////// using rule one and two ////////////////////
for(int i = 0;i < lineno;i++){
   iter = production[i].begin();
  // for tempory search
   hold1 = *iter; // it's the non-terminal
   iter++;
   iter++; // move backward for two step to get iter point to the
          //  right of the produciton
   tmp = iter; // use tmp now
   hold2 = *tmp; // hold for seaching
while(true){
    if(isIn(hold2,VT) || hold2 == ee){
       for(int k = 0;k < VN.size();k++)
          if(symbol[k].name == hold1 && !isIn(hold2,symbol[k].first))
             symbol[k].first.push_back(hold2);
        }
      while(tmp != production[i].end()){
          if(*tmp == "|"){
             tmp++;
             hold2 = *tmp;
             break;
           }
           tmp++;
        }
        if(tmp == production[i].end())
         break;
    }
  
}
      // second scan for the production A->X1..Xk
   /////////// second scan ///////////////////////////
  ///////// use the third rule ///////////////////////
  
while(cnt < CNT){ // for at most two times can get the first set
for(int line = 0;line < colineno;line++) {
   mark = 0;
    // in fact , this pass can be added to the first scan
   hold1 = coProduction[line].front(); // save for searching
    iter = coProduction[line].begin();
   iter++;
   iter++; // move backward to the first of the right
   flag = true; // set flag true
while(flag == true && iter != coProduction[line].end()){
       hold2 = *iter;
   if((isIn(hold2,VT) && mark == 0 ) || hold2 == ee) // if the current symbol is a terminal
       {mark++;  break ; }
       // add it directly
      // just ingore it
   else{ // the current symbol is a non-terminal
       for(int _i = 0;_i < VN.size();_i++)
         if(hold1 == symbol[_i].name)
           { save1 = _i;   break; }
        for(int _j = 0;_j < VN.size();_j++)
          if(hold2 == symbol[_j].name)
             {save2 = _j; break;}
     if(isIn(hold2,VT) && !isIn(hold2,symbol[save1].first) & hold2 != ee)
        symbol[save1].first.push_back(hold2);
      // after found the position ,let us copy it
        else{
         tmp = symbol[save2].first.begin();
        while(tmp != symbol[save2].first.end()){
          hold3 = *tmp;
          if(!isIn(hold3,symbol[save1].first) && hold3 != ee)
           symbol[save1].first.push_back(hold3);
           tmp++;
        }  
       }
      }   
        if(!isIn(ee,symbol[save2].first))
          flag = false; // set flag to false to end the loop
        iter++; // move backward
        if(flag == true && !isIn(ee,symbol[save1].first))
        symbol[save1].first.push_back(ee); // add e to the first
    }  
   }
   cnt++;
  }
}
//////////////////////////////////////////////
/////////// BUild FOLLOW Set finished on 6.8
////                ** Math Frog  ** /////////
/////////////////////////////////////////////
void buildFollow()
{
   list<string>::iterator iter,it,copy;
   int save,save1,save2;
   int cnt = 0;
   symbol[0].follow.push_back("$");
  while(cnt < _CNT){
    for(int line = 0;line < colineno;line++){
        iter = coProduction[line].begin();
        for(int k = 0;k < VN.size();k++)
         if(*iter == symbol[k].name)
           {save = k;break;}
         iter++;
         iter++;
while(iter != coProduction[line].end()){
     if(isIn(*iter,VN)){
           //// compute Xi+1Xi+2 ..Xn  ////////////////
       for(int i = 0;i < VN.size();i++)
            if(symbol[i].name == *iter)
              {save1 = i;break;}
   if(iter == --(coProduction[line].end()))
        {cofirst.push_back(ee); }
        else{
           it = iter;
            it++;
         while(it != coProduction[line].end()){
             if(isIn(*it,VT))
               {cofirst.push_back(*it);break;}
            else{
             for(int j = 0;j < VN.size();j++)
                   if(symbol[j].name == *it)
                     {save2 = j;break;}     
             for(copy = symbol[save2].first.begin();copy != symbol[save2].first.end();copy++)
                     if(!isIn(*copy,cofirst))
                        cofirst.push_back(*copy);
             }
           if(!isIn(ee,symbol[save2].first)) break;
              it++;
             }
          }
         for(copy = cofirst.begin();copy != cofirst.end();copy++)
               if(!isIn(*copy,symbol[save1].follow) && *copy != ee)
                 symbol[save1].follow.push_back(*copy);
        if(isIn(ee,cofirst)){
         for(copy = symbol[save].follow.begin();copy != symbol[save].follow.end();copy++)
           if(!isIn(*copy,symbol[save1].follow) && *copy != ee)
             symbol[save1].follow.push_back(*copy);
           }   
         }  
        cofirst.erase(cofirst.begin(),cofirst.end());
          iter++;
         }
      } // the loop for(;;)
     cnt++;
   } // scan times
}
void printFirst()
{
cout << "***********************************" << endl;
  cout << "** The FIRST sets are as follow **"<< endl;
  cout << "***********************************" << endl;
  for(int i_ = 0;i_ < VN.size();i_++){
  list<string>::iterator iter = symbol[i_].first.begin();
    cout << "FIRST" << "( " << symbol[i_].name << " ) = " << "{ ";
    while(iter != symbol[i_].first.end()){
       cout << *iter;
     if(iter != --symbol[i_].first.end())
       cout << ",";  // the output formation use my precious 3 minutes  :(
       iter++;
       }
       cout << " }" << endl;
   }
    cout << "***********************************" << endl;
    cout << endl;
}

  void printFollow()
{
cout << "***********************************" << endl;
cout << "** The FOLLOW sets are as follow **" << endl;
cout << "***********************************" << endl;
   for(int i = 0;i  < VN.size();i++){
   list<string>::iterator iter = symbol[i].follow.begin();
   cout << "Follow" << "( " << symbol[i].name << " ) = " << "{ ";
   while(iter != symbol[i].follow.end()){
    cout << *iter;
    if(iter != --symbol[i].follow.end())
     cout << ",";
     iter++;
   }
   cout << " }" << endl;
}
  cout << endl;
}

10 楼

请用DEV C++ 编译。。好运

我来回复

您尚未登录,请登录后再回复。点此登录或注册