1. 程式人生 > >遞迴下降語法分析實驗

遞迴下降語法分析實驗

一、實驗目的

通過設計、開發一個高階語言的遞迴下降語法分析程式,實現
對詞法分析程式所提供的單詞序列進行語法檢查和結構分析,加
深對相關課堂教學內容的理解,提高語法分析方法的實踐能力。

二、實驗要求

(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; }