主题:C++的词法和语法分析
			 belinda840117
				 [专家分:0]  发布于 2005-06-03 12:05:00
 belinda840117
				 [专家分:0]  发布于 2005-06-03 12:05:00							
			各位大虾啊,救救急好吗?本人将不胜感激!
 我急着交一个关于C++的词法和语法分析作业,
那个编译作业是这个样子的:
  
对C++进行词法和语法分析。
要求:
   词法分析部分写出相应的正规集、正规式、NFA、DFA   
   写出语法分析所采用的方法和完成的语法分析功能     
   编写出响应的编译程序     
   写出完整的课程设计报告
说明:课程设计报告包括的基本内容有:
一、课程设计题目
二、课程设计的目的
三、课程设计的基本内容和实现功能介绍
四、词法分析:包括系统的词法规则,相应的正规集、正规式、NFA、DFA
五、语法分析:包括语法规则,分析所采用的技术和算法
						
					 
		
			
回复列表 (共15个回复)
		
								
				沙发
				
					 tyu [专家分:20]  发布于 2005-06-07 22:43:00
tyu [专家分:20]  发布于 2005-06-07 22:43:00				
				不是吧
你大几了
要搞这个
							 
						
				板凳
				
					 compiler [专家分:80]  发布于 2005-06-09 23:30:00
compiler [专家分:80]  发布于 2005-06-09 23:30:00				
				前些日子写的LL(1)语法分析器。可以构造非递归的FIRST和FOLLOW集还有预测分析表。希望对你有帮助。好运。
							 
						
				3 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:31:00
compiler [专家分:80]  发布于 2005-06-09 23:31:00				
				
// 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:31:00
compiler [专家分:80]  发布于 2005-06-09 23:31:00				
				# 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:31:00
compiler [专家分:80]  发布于 2005-06-09 23:31:00				
				# 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:32:00
compiler [专家分:80]  发布于 2005-06-09 23:32:00				
				# 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:32:00
compiler [专家分:80]  发布于 2005-06-09 23:32:00				
				/*
 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:32:00
compiler [专家分:80]  发布于 2005-06-09 23:32:00				
				/*
 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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:32:00
compiler [专家分:80]  发布于 2005-06-09 23:32:00				
				/*
  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 楼
				
					 compiler [专家分:80]  发布于 2005-06-09 23:33:00
compiler [专家分:80]  发布于 2005-06-09 23:33:00				
				请用DEV C++ 编译。。好运
							 
									
			
我来回复