1、實驗目的:git
利用C語言編制遞歸降低分析程序,並對簡單語言進行語法分析。express
編制一個遞歸降低分析程序,實現對詞法分析程序所提供的單詞序列的語法檢查和結構分析。spa
2、實驗原理指針
每一個非終結符都對應一個子程序。blog
該子程序根據下一個輸入符號(SELECT集)來肯定按照哪個產生式進行處理,再根據該產生式的右端:遞歸
3、實驗要求說明string
輸入單詞串,以「#」結束,若是是文法正確的句子,則輸出成功信息,打印「success」,不然輸出「error」,並指出語法錯誤的類型及位置。it
例如:io
輸入begin a:=9;x:=2*3;b:=a+x end #編譯
輸出success
輸入x:=a+b*c end #
輸出‘end' error
4、實驗步驟
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"); }
運行結果