《編譯原理語法分析.doc》由會員分享,可在線閱讀,更多相關《編譯原理語法分析.doc(17頁珍藏版)》請在裝配圖網(wǎng)上搜索。
上機練習二:語法分析
一、根據(jù)上機練習一給出的PL/0語言擴充的巴克斯范式語法描述,利用遞歸下降的語法分析方法,編寫PL/0語言的語法分析程序。
要求:
1. 對給出的PL/0語言進行分析,證明其可以進行自上而下的語法分析;
2. 對block、proc、statement、condition、expression、term、factor進行分析,畫出語法分析圖,在此基礎上描述這些子程序的設計思想;
3. 具有一定的語法錯誤處理能力;
二、源代碼
#include
#include
#include
#include
#include
using namespace std;
struct yufa
{
string SYM; //單詞的類別
string strToken; //用戶所定義的標識符的值
int l; //記錄換行符的個數(shù),即記錄源文件的行數(shù)
}yufa0, yufa1, yufa2[1000];//yufa1用于保存各個單詞,yufa1用于詞法分析過程;yufa0主要用于語法分析;
char ch;
int mm= 0; //結構體數(shù)組下標
int line = 0;//出錯位置
//char ch = ;
string key[15] = { "begin", "end", "if", "then", "else", "while", "write", "read",
"do", "call", "const", "var", "procedure", "program", "odd" };//預設保留字
void prog();
void block();
void condecl();
void _const();
void vardecl();
void proc();
void body();
void statement();
void lexp();
void exp();
void term();
void factor();
void error0()
{
cout << "program標示符出錯" << endl;
exit(0); //出錯即退出
}
void error1()
{
cout << "第" << line << "行缺少分號" << endl;
}
void error2()
{
cout << "第" << line << "行標識符(變量名)出錯" << endl;
}
void error3()
{
cout << "第" << line << "常量未聲明(缺少const)" << endl;
}
void error4()
{
cout << "第" << line << "常量未賦值" << endl;
}
void error5()
{
cout << "第" << line << "賦值號出錯或者缺少賦值號" << endl;
}
void error6()
{
cout << "第" <,即標識符
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == ";")//;
{
mm++; yufa0.SYM = yufa2[mm].SYM;
block();
}
else error1();//缺少;
}
else error2();//缺少標識符或者標識符錯誤
}
else error0();
cout << "\n\n--------------------------語法分析結束------------------------\n\n" << endl;
}
void block()//程序體的遞歸子程序實現(xiàn), → [][][]
{
if (yufa0.SYM == "const")
condecl();
if (yufa0.SYM == "var")
vardecl();
if (yufa0.SYM == "procedure")
proc();
body();
}
void condecl()//常量說明的遞歸子程序實現(xiàn), → const {,};
{
line++;
if (yufa0.SYM == "const") // const
{
mm++; yufa0.SYM = yufa2[mm].SYM;
_const();//
while (yufa0.SYM == ",")//,逗號
{
mm++; yufa0.SYM = yufa2[mm].SYM;
_const();
}//
if (yufa0.SYM == ";")//;
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error1();//缺少;
}
else error3();//缺少常量定義const
}
void _const()//常量, → :=
{
if (yufa0.SYM == "biaoshifu") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "fuzhi")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "didit")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error4();//常量未賦值
}
else error5();//缺少賦值號,或者賦值號錯誤
}
else error2(); //缺少標識符
}
void vardecl()//變量說明的遞歸子程序實現(xiàn), → var {,};
{
line++;
if (yufa0.SYM == "var")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
while (yufa0.SYM == ",")//,
{
mm++; yufa0.SYM = yufa2[mm].SYM;//下一單詞
if (yufa0.SYM == "biaoshifu") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error2();//缺少標識符即缺少變量
}
if (yufa0.SYM == ";")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}//下一單詞
else error2();
}
}
else error6();//變量未聲明
}
void proc()// → procedure ({,});{;}
{
line++;
if (yufa0.SYM == "procedure") //procedure
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "(") //(
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu")//
{
mm++; yufa0.SYM = yufa2[mm].SYM;
while (yufa0.SYM == ",")// ,
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error2();
}
}
if (yufa0.SYM == ")")// )
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == ";") //;
{
mm++; yufa0.SYM = yufa2[mm].SYM;//下一單詞---------->>
block();
while (yufa0.SYM == ";")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
proc();
}
}
else error1();// 缺少;
}
else error7();//括號不匹配 (右括號少)
}
else error8();//左括號缺少
}
else error9();//缺少參數(shù)
}
else error10();//procedure錯誤
}
void body()// → begin {;}end
{
if (yufa0.SYM == "begin")
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
statement();
// while ((yufa0.SYM == "biaoshi") || (yufa0.SYM == "if") || (yufa0.SYM == "while") ||
// (yufa0.SYM == "call") || (yufa0.SYM == "read") || (yufa0.SYM == "write") || (yufa0.SYM == "begin"))
// error1();//語句未到最后一條,缺少";"
while(yufa0.SYM == ";")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
statement();
}
if (yufa0.SYM == "end")
{
line ++;
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error11();//缺少end與begin匹配
}
else error12();//缺少begin
}
// → := //語句
// |if then [else ]
// |while do
// |call [({,})]
// |
// |read ({,})
// |write ({,})
void statement()
{
if (yufa0.SYM == "biaoshifu") // → :=
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "fuzhi")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
exp();
}
else error5();//賦值號錯誤
}
else if (yufa0.SYM == "if") //if then [else ]
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
lexp();
if (yufa0.SYM == "then")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
statement();
if (yufa0.SYM == "else")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
statement();
}
}
else error12();//缺少then
}
else if (yufa0.SYM == "while")//while do
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
lexp();
if (yufa0.SYM == "do")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
statement();
}
else error13();//缺少do不匹配(while 與do 不匹配)
}
else if (yufa0.SYM == "call")//call [({,})]
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "(") //
{
mm++; yufa0.SYM = yufa2[mm].SYM;
while(yufa0.SYM == ",")
{
mm++;yufa0.SYM = yufa2[mm].SYM;
exp();
}
if (yufa0.SYM == ")")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error7();//缺少右括號
}
// 此處不會報錯,[({,})]因為表示可有可無的
}
else error14();//調(diào)用過程缺少標識符
}
else if (yufa0.SYM == "read")//read ({,})
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "(")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
while (yufa0.SYM == ",")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "biaoshifu")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error2();//缺少標示符
}
if (yufa0.SYM == ")")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error7();//缺少右括號
}
else error9();//read缺少參數(shù)
}
else error8();//缺少左括號
}
else if (yufa0.SYM == "write")//write ({,})
{
line++;
mm++; yufa0.SYM = yufa2[mm].SYM;
if (yufa0.SYM == "(")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
exp();
while (yufa0.SYM == ",")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
exp();
}
if (yufa0.SYM == ")")
{
mm++; yufa0.SYM = yufa2[mm].SYM;
}
else error7();//缺少右括號
}
else error8();//缺少左括號
}
else body();//
}
// → |odd
// → [+|-]{}
// → {}
//→||()
// → =|<>|<|<=|>|>=
// → +|-
// → *|/
// → l{l|d} (注:l表示字母)
// → dievbyqtbdd
void lexp()// → |odd
{
if (yufa0.SYM == "odd")
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
exp();
}
else
{
exp();
if ((yufa0.SYM == "ge") || (yufa0.SYM == "g") || (yufa0.SYM == "l") || (yufa0.SYM == "ne") || (yufa0.SYM == "l") || (yufa0.SYM == "="))
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
exp();
}
else
error15();//條件語句出錯,缺少界符
}
//odd是否存在?
}
void exp()// → [+|-]{}
{
while((yufa0.SYM == "+") || (yufa0.SYM == "-"))
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
term();//
}
term();
while ((yufa0.SYM == "+") || (yufa0.SYM == "-"))// → +|-
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
term();
}
}
void term()// → {}
{
factor();
while ((yufa0.SYM == "*") || (yufa0.SYM == "/"))// → *|/
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
factor();//factor()
}
}
void factor()//→||()
{
if (yufa0.SYM == "biaoshi")
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
}
else if (yufa0.SYM == "digit")
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
}
else if (yufa0.SYM == "(")
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
exp();
if (yufa0.SYM == ")")
{
mm++;
yufa0.SYM = yufa2[mm].SYM;
}
else error7(); //缺少右括號
}
else error8();//缺少左括號
}
string Concat(char ch,string strToken)
{
strToken += ch;
return strToken;
}
int IsLetter(char c ) //判斷字母
{
if (((c <= z)&&(c >= a)) || ((c <= Z)&&(c >= A)))
return 1;
else return 0;
}
int IsDigit(char c) //判斷數(shù)字
{
if ((c >= 0)&&(c <= 9))
return 1;
else return 0;
}
int IsKey(string StrToken) //判斷保留字
{
int i;
for (i = 0; i<15; i++)
{
if (key[i].compare(StrToken) == 0)
return 1;
}
return 0;
}
void getsym(fstream &file)
{
string StrToken = "";
// if (ch == || ch == \t || ch == \n) //濾掉空白字符
// ch = file.get();
if (IsLetter(ch))
{
while (IsLetter(ch) || IsDigit(ch))
{
StrToken = Concat(ch,StrToken);
ch = file.get();
}
if (IsKey(StrToken))
{
int i;
for (i = 0; i<15; i++)
{
if (key[i].compare(StrToken) == 0)
yufa1.SYM = key[i];
}
yufa1.strToken = StrToken;
}
else
{
yufa1.SYM = "biaoshifu";
yufa1.strToken = StrToken;
}
}
if (IsDigit(ch))
{
StrToken = "";
while(IsDigit(ch))
{
StrToken = Concat(ch,StrToken);
ch = file.get();
}
if(IsLetter(ch)) //數(shù)字后面跟字母,錯誤詞法
{
while(IsLetter(ch)||IsDigit(ch))
{
StrToken = Concat(ch,StrToken);
ch = file.get();
}
cout <<"詞法錯誤!(數(shù)字后面跟字母) "<< StrToken<< endl;
}
else
yufa1.SYM = "digit";
yufa1.strToken = StrToken;
}
else switch (ch)
{
case+:{yufa1.SYM = "+";yufa1.strToken = "+";ch = file.get();break;}
case-:{yufa1.SYM = "-";yufa1.strToken = "-";ch = file.get();break;}
case*:{yufa1.SYM = "*";yufa1.strToken = "*";ch = file.get();break;}
case/:{yufa1.SYM = "/";yufa1.strToken = "/";ch = file.get();break;}
case(:{yufa1.SYM = "(";yufa1.strToken = "(";ch = file.get();break;}
case):{yufa1.SYM = ")";yufa1.strToken = ")";ch = file.get();break;}
case=:{yufa1.SYM = "=";yufa1.strToken = "=";ch = file.get();break;}
case;:{yufa1.SYM = ";";yufa1.strToken = ";";ch = file.get();break;}
case,:{yufa1.SYM = ",";yufa1.strToken = ",";ch = file.get();break;}
case::
{
ch = file.get();
if (ch == =)
{
yufa1.SYM = "fuzhi";
yufa1.strToken = ":=";
}
else
cout << ":" << "詞法錯誤(:后面沒有=)" << endl;
ch = file.get();
break;
}
case>:
{
ch = file.get();
if (ch == =)
{
yufa1.SYM = "ge";
yufa1.strToken = ">=";
}
else
{
yufa1.SYM = "g";
yufa1.strToken = ">";
}
ch = file.get();
break;
}
case<:
{
ch = file.get();
if (ch == =)
{
yufa1.SYM = "le";
yufa1.strToken = "<=";
}
else if (ch == >)
{
yufa1.SYM = "ne";
yufa1.strToken = "<>";
}
else
{
yufa1.SYM = "l";
yufa1.strToken = "<";
}
ch = file.get();
break;
}
}
}
int main()
{
int nn = 0;
string StrToken = "";
fstream file;
char ch;
int ll;
char filename[30];
cout << "請輸入源文件名:";
cin.getline(filename, 30);
file.open(filename, ios::in);
if (!file)
{
cout << "文件打開失敗!\n\n";
exit(0);
}
yufa2[nn].l = 0;
cout << "\n--------------------------詞法分析------------------------" << endl;
// ch = file.get();
while (!file.eof())
{
// if (ch == || ch == \t || ch == \n) //濾掉空白字符
// ch = file.get();
// ch = file.get();
if (ch == || ch == \t)
ch=file.get();
while (ch == \n)
{
ll ++;
ch = file.get();
}
getsym(file);
nn++;
yufa2[nn].SYM = yufa1.SYM;
yufa2[nn].strToken = yufa1.strToken;
yufa2[nn].l = ll;
// cout.setf(ios::left);
cout << "(" << setw(2) << nn << ") ";
cout << setw(13) << yufa2[nn].SYM << setw(9) << yufa2[nn].strToken << "\n";
cout << setw(13) << yufa1.SYM << setw(9) << yufa1.strToken << "\n";
}
// nn++;
// yufa2[nn].SYM = "the_end";//完成
// yufa2[nn].strToken = "the_end";
file.close();
// cout << "\n\n\n--------------------------語法分析------------------------" << endl;
yufa0.SYM = yufa2[mm].SYM;
// yufa0.SYM = yufa1.SYM;
prog();
return 0;
}
鏈接地址:http://www.820124.com/p-6675334.html