一、实验目的:

利用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

#include

#include

//程序段 单词

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 '

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");

}

运行结果

利用c语言编制1个程序,实现对给定语法句子的递归下降分析.,递归下降语法分析 - osc_3ubrwgtm的个人空间 - OSCHINA - 中文开源技术交流社区...相关推荐

  1. 方阵循环右移c语言,C语言第二次实验报告 - osc_zfz30hgc的个人空间 - OSCHINA - 中文开源技术交流社区...

    #一.实验题目,设计思路与实现方法 题目一 11-6 方阵循环右移(20 分) 本题要求编写程序,将给定n×n方阵中的每个元素循环向右移m个位置,即将第0.1.⋯.n−1列变换为第n−m.n−m+1. ...

  2. C语言包含特殊寄存器文件ch,c语言第二次实验报告 - osc_zfz30hgc的个人空间 - OSCHINA - 中文开源技术交流社区...

    一.实验题目,设计思路,实现方法 题目一:11-4 判断上三角矩阵 编写一个程序,判断一个矩阵是不是上三角矩阵. 问题:循环条件设置不当,导致错误的重复判断,最终导致结果错误. 题目二:12-8 删除 ...

  3. java实现自举_实现语言的自举 - 沙枣的个人空间 - OSCHINA - 中文开源技术交流社区...

    几乎所有的语言项目,其核心都是用更底层的语言写的. 底层语言大部分是 C,C++,而扩展这门语言的核心,就要用另外一种语言 去写.这给语言设计者较大的挑战. 开发语言必须具备底层语言的编写能力,而为了 ...

  4. 仿射解密c语言程序实验报告,仿射加密解密 - 依姆哣特的个人空间 - OSCHINA - 中文开源技术交流社区...

    //功能:仿射加密 密钥:[3][5][9][11][15][17][19][21][23]有逆元的数 例子:pku  c=7,d=3  输出 :EVN 编辑环境:vc++6.0 include in ...

  5. 微信步数C语言程序,获取微信步数 - osc_1v2pb1nt的个人空间 - OSCHINA - 中文开源技术交流社区...

    const util = require('../../utils/util.js') Page({ /** * 页面的初始数据 */ data: { runData:[], }, /** * 生命周 ...

  6. python语言是由谁设计并领导开发的_python语言概述 - osc_lt3ocv4d的个人空间 - OSCHINA - 中文开源技术交流社区...

    python语言的发展 python语言诞生于1990年,由Guide van Rossum设计并领导开发. python语言是开源项目的优秀代表,其解释器的全部代码都是开源的. 编写Hello程序 ...

  7. 按照c语言规首字母只能是,C语言--指针 - osc_nbqoh20k的个人空间 - OSCHINA - 中文开源技术交流社区...

    [TOC] #知识内容总结 ##为什么要学习指针? 我们已经学习了如何用数组存放多个相同类型的数据并进行运算,但数组的长度在定义时必须给定以后不能再改变.如果事先无法确定需要处理数据数量,应该如何处理 ...

  8. C语言十个字母用冒泡法排序,冒泡排序法(C语言) - osc_wq8j2a9a的个人空间 - OSCHINA - 中文开源技术交流社区...

    常用的排序方法有冒泡排序法,选择排序法,插入排序法以及希尔排序法等.本文着重讲解如何利用C代码,实现冒泡排序. 首先,要了解什么是冒泡排序.冒泡排序是常用的一种排序方法,其基本方法就是逐次比较.即一次 ...

  9. 何杰月c语言课程,多线程 - 何杰leo的个人空间 - OSCHINA - 中文开源技术交流社区...

    多线程--百度百科:多线程(英语:multithreading),是指从软件或者硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性 ...

  10. c语言处理字符串函数的头文件,C语言字符处理函数 - 20131125的个人空间 - OSCHINA - 中文开源技术交流社区...

    C语言提供了丰富的字符串处理函数, 大致可分为字符串的输入.输出.合并.修改.比较.转换.复制.搜索几类. 使用这些函数可大大减轻编程的负担.用于输入输出的字符串函数,在使用前应包含头文件" ...

最新文章

  1. php当前页面的链接地址,PHP 技巧:如何获取当前页面的链接地址
  2. 虚拟主机众多用途你心仪哪一项?
  3. UML--9种图及关系
  4. DataSet DataTable操作
  5. Python3中的 Filter的改变
  6. [Python3]Python面向对象的程序设计
  7. Full_of_Boys训练2总结
  8. [渝粤教育] 山东第一医科大学 健康教育与健康促进 参考 资料
  9. 并发编程-concurrent指南-原子操作类-AtomicBoolean
  10. Magento搬家、换域名、重新安装教程
  11. 著名NFT藏家WhaleShark的NBA Top Shot账户估值达1580万美元
  12. MongoDB中常用的几种数据类型
  13. python樱花_如何基于python实现画不同品种的樱花树
  14. mayan 游戏真是毒瘤
  15. Easyui datagrid getData简单使用
  16. php开发人脸识别流程,php使用face++实现一个简单的人脸识别系统
  17. Windows server2012r2安装密钥
  18. AHP中特征向量、权重值、CI值等指标如何计算?
  19. 巧用 arp 命令 防p2p终结者的方法
  20. PL2303HXD驱动

热门文章

  1. tomcat运行的本质
  2. 图像中有关位图、色位图、以及所占字节数
  3. iOS - 常用本机URL跳转设置
  4. JEPLUS平台JS事件的操作技巧——JEPLUS软件快速开发平台
  5. Carthage 安装与使用
  6. java中String的特点,字面对象和构造方法的区别
  7. 同步与异步、异步与回调
  8. Mysql 的 Cascade Restrict
  9. Windows Phone 7 使用Perst数据库的Demo——流水账
  10. 子窗体闭关后刷新父窗体内容