遞迴下降語法分析實驗
一、實驗目的
通過設計、開發一個高階語言的遞迴下降語法分析程式,實現
對詞法分析程式所提供的單詞序列進行語法檢查和結構分析,加
深對相關課堂教學內容的理解,提高語法分析方法的實踐能力。
二、實驗要求
(1)理解語法分析在編譯程式中的作用,以及它與詞法分析程式的
關係;
(2)掌握遞迴下降語法分析方法的主要原理;
(3)理解遞迴下降分析法對文法的要求;
(4)熟練掌握Select集合的求解方法;
(5)熟練掌握文法變換方法(消除左遞迴和提取公因子)。
三、實驗原理
遞迴下降分析法是語法分析中最易懂的一種方法,基本原理
是:對每個非終結符號(分別代表一個語法單位)按其產生式結
構構造相應語法分析子程式,以完成該非終結符號所對應的語法
單位的分析和識別任務。其中終結符號產生匹配命令,而非終結
符號則產生過程呼叫命令。因為文法可以遞迴,相應子程式也是
遞迴的,所以稱這種方法為遞迴子程式下降法或遞迴下降法。其
中子程式的結構與產生式結構幾乎是一致的。
《編譯原理》實驗指導書
假設一個文法中的非終結符號A 的全部產生式為
A��α1|α2|……|αn ,則必須滿足以下條件才能保證可以唯一的選
擇合適的產生式,才能採用遞迴下降分析法:
Select(A��αi)∩Select(A��αj)=Φ,其中i≠j
假設文法中有如下的產生式A��β1|β2|…|βn,則應按如下方法
編寫語法分析子程式。
四、實驗步驟
(1)根據S語言BNF形式的語法規則(見附件A),寫出S語言的上下
文無關文法;
(2)求每個產生式的Select集:
procedure A( )
begin if token∈Select(A��β1) then θ(β1) else
if token∈Select(A��β2) then θ(β2) else
……
if token∈Select(A��βn) then θ(βn) else
error()
end
其中 βi =X1X2…Xn,θ(βi) =θ’(X1); θ’(X2);…; θ’(Xn);如果
Xi∈VN,θ’(Xi)= Xi;如果Xi∈VT,θ’(Xi)= Match(Xi);如果Xi= ε,
θ’(Xi) = skip(空語句)。
《編譯原理》實驗指導書
10
Select(A��β)= First(β),當 ε∉First(β)
= (First(β)-{ε})∪Follow(A),當ε∈First(β)
(3)判斷是否滿足遞迴下降法分析條件,若不滿足用消除左遞迴和
提取公因子等文法等價變換操作對文法進行變換,使其滿足遞
歸下降法的要求;
(4)構造遞迴下降語法分析程式,對文法中的每個非終結符號按其
產生式結構產生相應的語法分析子程式,完成相應的識別任
務。其中終結符號產生匹配命令,非終結符號則產生呼叫命令。
實際的語法分析工作從呼叫主程式(開始符號S對應的程式)
開始,根據產生式遞迴呼叫各個分析子程式;
(5)撰寫實驗報告。
程式碼
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
void Print();
void Scanner();
bool Statement();
bool Condition();
bool While_Statement();
bool Expression();
bool Item_expression();
bool Factor();
bool Conditional_statements();
bool Assignment_statement();
bool Compound_statements();
int syn;//存放單詞的型別
int p;
char ch;
int sum;//用來儲存數字的值
char program[200],token[10];
char *rwtab[9]={"begin","if","then",
"else","while","do","Const"
,"Var","end"};
int m;
bool isDigital(char ch)
{
if(ch<='9'&&ch>='0')
return true;
else
return false;
}
bool isAlpha(char ch)
{
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
return true;
else
return false;
}
void Scanner()
{
int num=0;
for(m=0;m<10;m++)
{
token[m]='\0';
}
m=0;
ch=program[p++];
while(ch==' '||ch=='\n'||ch=='\t')
{
ch=program[p++];
}
if(isAlpha(ch)){
do{
token[m++]=ch;
ch=program[p++];
}while(isAlpha(ch)||isDigital(ch));
p--;
syn=10;
token[m++]='\0';
for(int n=0;n<=8;n++)
{
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
return;
}
else if(isDigital(ch))
{
sum=0;
while(isDigital(ch))
{
sum=sum*10+ch-'0';
ch=program[p++];
}
p--;
syn=11;
if(isAlpha(ch))
syn=-1;
return;
}
else
{
token[0]=ch;
switch(ch)
{
case '<':ch=program[p++];
if(ch=='>')
{
syn=22;
token[1]=ch;
}
else if(ch=='=')
{
syn=18;
token[1]=ch;
}
else{
syn=19;
p--;
}
break;
case '>':ch=program[p++];
if(ch=='=')
{
syn=21;
token[1]=ch;
}
else{
syn=20;
p--;
}
break;
case '=':ch=program[p++];
if(ch=='=')
{
syn=17;
token[1]=ch;
}
else{
syn=16;
p--;
}
break;
case '+':syn=12;break;
case '-':syn=13;break;
case '*':syn=14;break;
case '/':syn=15;break;
case ';':syn=23;break;
case '(':syn=24;break;
case ')':syn=25;break;
case ',':syn=26;break;
case '#':syn=0;break;
default:syn=-1;break;
}
return;
}
}
bool Constan_Defined()
{
if(syn==10)
{
cout<<"常量定義"<<token<<endl;
Scanner();
if(syn==16)
{
cout<<"等於"<<token<<endl;
Scanner();
if(syn==11)
{
cout<<"無符號整數"<<sum<<endl;
return true;
}
return false;
}
return false;
}
return false;
}
bool Constan_Description()
{
Scanner();
if(syn==7)
{
cout<<"常量說明"<<token<<endl;
Scanner();
while(Constan_Defined())
{
Scanner();
if(syn==23)
{
cout<<"分號"<<token<<endl;
return true;
}
else if(syn==26)
{
cout<<"逗號"<<token<<endl;
Scanner();
continue;
}
cout<<"常量說明錯誤"<<endl;
}
}
else
return false;
}
bool Variable_Defined()
{
if(syn==10)
{
cout<<"變數定義"<<token<<endl;
return true;
}
else
return false;
}
bool Variable_Description()
{
if(syn==10||syn==2||syn==5||syn==1||syn==0)
{
return true;
}
Scanner();
if(syn==8)
{
cout<<"變數說明"<<token<<endl;
Scanner();
while(Variable_Defined())
{
Scanner();
if(syn==23)
{
cout<<"分號"<<token<<endl;
return true;
}
else if(syn==26)
{
cout<<"逗號"<<token<<endl;
Scanner();
continue;
}
}
}
}
bool Condition()
{
cout<<"條件"<<endl;
Expression();
if(syn==17||syn==18||syn==19||syn==20||syn==21
||syn==22)
{
cout<<"關係運算符"<<token<<endl;
Scanner();
}
else
{
cout<<"關係運算符錯誤"<<endl;
return false;
}
Expression();
}
bool Expression()
{
cout<<"表示式"<<endl;
//Scanner();
do{
if(syn==12||syn==13)
{
cout<<"加法運算子"<<token<<endl;
Scanner();
Item_expression();
}
else
{
Item_expression();
}
}while(syn==12||syn==13);
return true;
}
bool Item_expression()
{
cout<<"項"<<endl;
while(Factor())
{
//Scanner();
if(syn==14||syn==15)
{
cout<<"乘法運算子"<<token<<endl;
Scanner();
}
else{
return true;
}
}
return false;
}
bool Factor()
{
cout<<"因子"<<endl;
//Scanner();
if(syn==10)
{
cout<<"識別符號"<<token<<endl;
Scanner();//特殊
return true;
}
else if(syn==11)
{
cout<<"無符號數字"<<sum<<endl;
Scanner();
return true;
}
else if(syn==24)
{
cout<<"左括號"<<token<<endl;
Scanner();
Expression();
if(syn==25)
{
cout<<"右括號"<<token<<endl;
Scanner();
return true;
}
else
{
cout<<"沒有),錯誤"<<endl;
return false;
}
}
else
{
cout<<"沒有左括號"<<endl;
return false;
}
return false;
}
bool Assignment_statement()
{
cout<<"賦值語句"<<endl;
cout<<"識別符號"<<token<<endl;
Scanner();
if(syn==16)
{
cout<<"賦值語句="<<endl;
Scanner();
Expression();
return true;
}
else
{
cout<<"沒有="<<endl;
}
}
bool Compound_statements()
{
cout<<"複合語句"<<token<<endl;
Scanner();
while(Statement())
{
if(syn==23)
{
cout<<"複合語句中的分割符"<<token<<endl;
Scanner();
if(syn==9) {
//cout<<"複合語句"<<token<<endl;
break;
}
}
}
if(syn==9)
{
cout<<"複合語句"<<token<<endl;
Scanner();
return true;
}
else
{
cout<<"複合語句缺乏"<<endl;
return false;
}
if(syn==0)
{
cout<<"複合語句"<<token<<endl;
}
}
bool Conditional_statements()
{
if(syn==2)
{
cout<<"條件語句if"<<endl;
Scanner();
Condition();
if(syn==3)
{
cout<<"then"<<endl;
Scanner();
Statement();
if(syn==4)
{
Scanner();
Statement();
}
else
{
return true;
}
}
else
{
cout<<"條件語句中缺少 then"<<endl;
return false;
}
}
else
{
return false;
}
}
bool While_Statement()
{
cout<<"迴圈語句"<<token<<endl;
Scanner();
Condition();
if(syn==6)
{
cout<<"while迴圈的do"<<endl;
Scanner();
Statement();
return true;
}
// else
// return false;
else
return false;
}
bool Statement()
{
if(syn==10)
{
Assignment_statement();
return true;
}
else if(syn==5)
{
While_Statement();
return true;
}
else if(syn==1)
{
Compound_statements();
return true;
}
else if(syn==2)
{
Conditional_statements();
return true;
}
else
{
return false;
}
}
int main()
{
printf("輸入語法分析串以#作為結束\n");
do
{
ch=getchar();
program[p++]=ch;
}while(ch!='#');
p=0;
cout<<"程式開始"<<endl;
Constan_Description();
Variable_Description();
do{
Scanner();
Statement();
}while(syn!=0);
cout<<"程式結束"<<endl;
}