一、实验目的:
利用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"); }
运行结果