遞歸下降語法分析

一、實驗目的:

利用C語言編制遞歸下降分析程序,並對簡單語言進行語法分析。

編制一個遞歸下降分析程序,實現對詞法分析程序所提供的單詞序列的語法檢查和結構分析。

 

二、實驗原理

每個非終結符都對應一個子程序。

該子程序根據下一個輸入符號(SELECT集)來確定按照哪一個產生式進行處理,再根據該產生式的右端:

  • 每遇到一個終結符,則判斷當前讀入的單詞是否與該終結符相匹配,若匹配,再讀取下一個單詞繼續分析;不匹配,則進行出錯處理
  • 每遇到一個非終結符,則調用相應的子程序

 

三、實驗要求說明

輸入單詞串,以“#”結束,如果是文法正確的句子,則輸出成功信息,打印“success”,否則輸出“error”,並指出語法錯誤的類型及位置。

例如:

輸入begin a:=9;x:=2*3;b:=a+x end #

輸出success

輸入x:=a+b*c  end #

輸出‘end' error

 

四、實驗步驟

1.待分析的語言的語法(參考P90)

2.將其改爲文法表示,至少包含

–語句

–條件

–表達式

3. 消除其左遞歸

4. 提取公共左因子

5. SELECT集計算

6. LL(1)文法判斷

7. 遞歸下降分析程序

各種單詞符號對應的種別碼

單詞符號 種別碼 單詞符號 種別碼
begin 1 : 17
if 2 := 18
then 3 < 20
while 4 <> 21
do 5 <= 22
end 6 > 23
letter(letter+digit)* 10 >= 24
digit* 11 = 25
+ 13 : 26
- 14 ( 27
* 15 ) 28
/ 16 # 0

#include<stdio.h>


#include<stdlib.h> #include<string.h> //程序段 單詞 char prog[800], dc[8]; //單詞中的字符 char ch; //單詞符號種別碼 int syn, p, m = 0; //整數sum int n, sum = 0; //保留字 char *word[6] = { "begin","if","then","while","do","end" }; //判斷是否有錯誤 int kk = 0; void scaner(); void lrparser(); void yucu(); void statement(); void condition(); void expression(); void term(); void factor(); void scaner() { m = 0; for (n = 0; n < 8; n++) { dc[n] = NULL; } ch = prog[p++]; while (ch == ' ') { ch = prog[p]; //指針+1往後移一位 p++; } //判斷輸入是否位數字或字母 if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { m = 0; while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z')) { dc[m++] = ch; ch = prog[p++]; } p--; syn = 10; //保留字 for (n = 0; n < 6; n++) { if (strcmp(dc, word[n]) == 0) { syn = n + 1; break; } } } //數字 else if ((ch >= '0'&&ch <= '9')) { sum = 0; while ((ch >= '0'&&ch <= '9')) { sum = sum * 10 + ch - '0'; ch = prog[p++]; } p--; syn = 11; } else { switch (ch) { case '<':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '>') { syn = 22; dc[m++] = ch; } else if (ch == '=') { syn = 21; dc[m++] = ch; } else { syn = 20; p--; } break; case '>':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '=') { syn = 24; dc[m++] = ch; } else { syn = 23; p--; } break; case ':':m = 0; dc[m++] = ch; ch = prog[p++]; if (ch == '=') { syn = 18; dc[m++] = ch; } else { syn = 17; p--; } break; case '*': syn = 15; dc[0] = ch; break; case '/': syn = 16; dc[0] = ch; break; case '+': syn = 13; dc[0] = ch; break; case '-': syn = 14; dc[0] = ch; break; case '=': syn = 25; dc[0] = ch; break; case ';': syn = 26; dc[0] = ch; break; case '(': syn = 27; dc[0] = ch; break; case ')': syn = 28; dc[0] = ch; break; case '#': syn = 0; dc[0] = ch; break; case '\n': syn = -2; dc[0] = ch; break; } } } //判斷是否以begin開始,end #結束 void lrparser() { //begin if (syn == 1) { scaner(); yucu(); //end if (syn == 6) { scaner(); if (syn == 0 && kk == 0) { printf("success \n"); } } else { printf("編譯出錯,缺少 'end' ! \n"); kk = 1; exit(0); } } else { printf("編譯出錯缺少 'begin' ! \n"); kk = 1; exit(0); } return; } //語句串 void yucu() { statement(); while (syn == 26) { scaner(); statement(); } return; } //語句 void statement() { //爲標識符 if (syn == 10) { scaner(); if (syn == 18) { //:= scaner(); expression(); } else { printf("error!"); kk = 1; exit(0); } } else if (syn == 2) { //if condition(); scaner(); if (syn == 3) { statement(); } else { printf("編譯出錯缺少 'then' ! \n"); kk = 1; exit(0); } } else { printf("error!"); kk = 1; exit(0); } return; } //條件 void condition() { expression(); if (syn == 25 || syn == 0 || syn == 20 || syn == 21 || syn == 23 || syn == 24) { scaner(); } else { printf("error! \n"); kk = 1; exit(0); } expression(); return; } //表達式 void expression() { term(); while (syn == 13 || syn == 14) { scaner(); term(); } return; } //項 void term() { factor(); while (syn == 15 || syn == 16) { scaner(); factor(); } return; } //因子 void factor() { if (syn == 10 || syn == 11) { //爲標識符或整常數時,讀下一個單詞符號 scaner(); } else if (syn == 27) { scaner(); expression(); if (syn == 28) { scaner(); } else { printf(" ')' 錯誤\n"); kk = 1; exit(0); } } else { printf("表達式錯誤\n"); kk = 1; exit(0); } return; } int main(void) { //從0開始逐個讀取 p = 0; int i; printf("請輸入源程序:\n"); do { scanf("%c", &ch); prog[p++] = ch; } while (ch != '#'); //指針從0開始 p = 0; do { scaner(); lrparser(); } while (syn != 0); printf("語法分析結束!\n"); }


運行結果

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章