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