递归下降语法分析

Posted lzhdonald

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了递归下降语法分析相关的知识,希望对你有一定的参考价值。

一、实验目的:

利用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 ‘ ‘: 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 "); } } else { printf("编译出错,缺少 ‘end‘ ! "); kk = 1; exit(0); } } else { printf("编译出错缺少 ‘begin‘ ! "); 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‘ ! "); 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! "); 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(" ‘)‘ 错误 "); kk = 1; exit(0); } } else { printf("表达式错误 "); kk = 1; exit(0); } return; } int main(void) { //从0开始逐个读取 p = 0; int i; printf("请输入源程序: "); do { scanf("%c", &ch); prog[p++] = ch; } while (ch != ‘#‘); //指针从0开始 p = 0; do { scaner(); lrparser(); } while (syn != 0); printf("语法分析结束! "); }


运行结果

技术图片

 技术图片

 

 

 

 

 

以上是关于递归下降语法分析的主要内容,如果未能解决你的问题,请参考以下文章

递归下降语法分析

递归下降语法分析

递归下降语法分析

递归下降语法分析器

实验二 递归下降语法分析

实验二 递归下降语法分析