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

