目的和内容

1、 实验目的:通过完成语法分析程序,了解语法分析的过程和作用
2、 实验内容:用递归子程序法实现对pascal的子集程序设计语言的分析程序
3、 实验要求:对源程序的内码流进行分析,如为文法定义的句子输出”是”否则输出”否”,根据需要处理说明语句填写写相应的符号表供以后代码生成时使用

文法的改变

为适合递归子程序法,对实验一中的文法改写成无左递归和无左共因子的BNF如下:
<程序>→<程序首部><分程序>.
<程序首部>→PROGRAM标识符;
<分程序>→<常量说明部分><变量说明部分><过程说明部分> <复合语句>
<常量说明部>→CONST<常量定义><常量定义后缀> |ε
<常量定义>→标识符=无符号整数
<常量定义后缀>→,<常量定义><常量定义后缀> |ε
<变量说明部分>→VAR<变量定义><变量定义后缀> |ε
<变量定义>→标识符<标识符后缀>:<类型>;
<标识符后缀>→,标识符<标识符后缀> |ε
<变量定义后缀>→<变量定义><变量定义后缀> |ε
<类型>→INTEGER | LONG
<过程说明部分>→<过程首部><分程序>;<过程说明部分后缀>|ε
<过程首部>→PROCEDURE标识符<参数部分>;
<参数部分>→(标识符: <类型>)|ε
<过程说明部分后缀>→<过程首部><分程序>;<过程说明部分后缀>|ε
<语句>→<赋值或调用语句>|<条件语句>|<当型循环语句>|<读语句>
|<写语句>|<复合语句>|ε
<赋值或调用语句>→标识符<后缀>
<后缀>→:=<表达式>|(<表达式>)|ε
<条件语句>→IF<条件>THEN<语句>
<当型循环语句>→WHILE<条件>DO <语句>
<读语句>→READ(标识符<标识符后缀>)
<写语句>→WRITE(<表达式><表达式后缀>)
<表达式后缀>→,<表过式><表达式后缀>|ε
<复合语句>→BEGIN<语句><语句后缀>END
<语句后缀>→;<语句><语句后缀>|ε
<条件>→<表达式><关系运算符><表达式>|ODD<表达式>
<表达式>→+<项><项后缀>|-<项><项后缀>|<项><项后缀>
<项后缀>→<加型运算符><项><项后缀>|ε
<项>→<因子><因子后缀>
<因子后缀>→<乘型运算符><因子><因子后缀>|e
<因子>→标识符|无符号整数|(<表达式>)
<加型运算符>→+|-
<乘型运算型>→*|/
<关系运算符>→ =|<>|<|<=|>|>=

非终结符和函数名对照表

为适用递归子程序,下表为非终结符和函数名对照表

非终结符

函数名

非终结符

函数名

<程序>

program

<程序首部>

proghead

<分程序>

block

<常量说明部分>

consexpl

<常量定义>

consdefi

<变量说明部分>

varexl

<常量定义后缀>

conssuff

<变量定义>

vardefi

<变量定义后缀>

varsuff

<>过程说明部分>

procdefi

<类型>

typeil

<过程首部>

procedh

<过程说明部分后缀>

procsuff

<赋值或调用语句>

assipro

<语句>

sentence

<后缀>

suffix

<条件语句>

ifsent

<读语句>

read

<当型循环语句>

whilsent

<标识符后缀>

idsuff

<写语句>

Write

<复合语句>

compsent

<表达式后缀>

Exprsuff

<语句后缀>

sentsuff

<条件>

Conditio

<项后缀>

termsuff

<表达式>

Express

<项>

term

<因子后缀>

Factsuff

<参数部分>

argument

<因子>

Factor

<加型运算符>

addoper

<乘型运算符>

Muloper

<关系运算符>

respoper

递归子程序的设计思想

为每个非终结符设计一个识别的子程序,寻找该非终结符也就是调用相应的子程序。由于单词在语法分析中作为一个整体,故在语法识别中仅使用其内码。在这里将词法分析作为语法分析的一个子程序,当语法分析需要单词时,就调用相应的词法分析程序获得一个单词。语法分析的作用是识别输入符号串是否是文法上定义的句子,即判断输入符号串是否是满足“程序”定义的要求。也就是当语法识别程序从正常退出表示输入符号串是正确的“程序”;若从出错退出,则输入符号串不是正确的“程序”。出错时,可以根据读字符的位置判断出错的位置。

实验流程

下面是部分子程序的流程图


实验代码

#include<bits/stdc++.h>
using namespace std;
#define PROGRAM 1
#define CONST 2
#define VAR 3
#define INTEGER 4
#define LONG 5
#define PROCEDURE 6
#define IF 7
#define THEN 8
#define WHILE 9
#define DO 10
#define READ 11
#define WRITE 12
#define BEGIN 13
#define END 14
#define ODD 15
#define ADD 16
#define SUB 17
#define MUL 18
#define DIV 19
#define EQU 20
#define NEQ 21
#define LES 22
#define LEQ 23
#define LAG 24
#define GEQ 25
#define DOT 26
#define COM 27
#define SEM 28
#define COL 29
#define ASS 30
#define LBR 31
#define RBR 32
#define INT 33
#define ID 34
#define EIN 35
#define lenth1 15
#define lenth2 17
struct Ident
{char name[21];int type;int addr;
};
Ident indent[1000]; // 定义标识符表
struct St
{char name[21];int code;
};
St sym;int lenth = 0;  // 表示标识符表长度
FILE* f1, * f2; //f1、f2分别指向输入输出文件int line = 0, row = 0, val;
void getsym();char getchr();void error(int);
void program(); void proghead();
void block(); void consexpl();
void consdefi(); void varexpl();
void conssuff(); void vardefi();
void varsuff(); void procdefi();
void typeil(); void procedh();
void procsuff(); void assipro();
void sentence(); void suffix();
void ifsent(); void read();
void whilsent(); void idsuff();
void write(); void compsent();
void exprsuff(); void sentsuff();
void conditio(); void termsuff();
void express(); void term();
void factsuff(); void argument();
void factor(); void addoper();
void muloper(); void respoper();int main(int argc, char* argv[]) {if ((f1 = fopen(argv[1], "r")) == NULL) {  // 打开输入文件流cout << "can not open the input file!" << endl;exit(0);}getsym();program();cout << "该程序通过语法分析!" << endl;fclose(f1);return 0;
}void getsym() {static char a[lenth1][10] = {"program","const","var","integer","long","procedure","if","then","while","do","read","write","begin","end","odd"},d[lenth2][3] = { "+","-","*","/","=","<>","<","<=",">",">=",".",",",";",":",":=","(",")" },str[21], ch = ' ';int i, n; // n判断单词长度,i判断是哪个关键字while (isspace(ch)){ch = getchr();}if (isalpha(ch)) { //判断字母开头的字符n = 0;while (isalpha(ch) || isdigit(ch)) {if (isalpha(ch))ch = tolower(ch);str[n++] = ch;ch = getchr();}str[n] = '\0';for (i = 0;i < lenth1;i++) {if (!strcmp(str, a[i]))break;}if (i < lenth1) { //找到匹配关键字strcpy(sym.name, a[i]);sym.code = i + 1;}else {for (i = 0;i < lenth;i++) { //遍历已记录的标识符记录表if (!strcmp(str, indent[i].name))break;}if (i == lenth) {strcpy(indent[i].name, str);}strcpy(sym.name, indent[i].name);sym.code = 34;}}else if (isdigit(ch)) { // 判断数字开头的字符val = 0;n = 0;while (isdigit(ch)) {val = val * 10 + ch - '0';sym.name[n++] = ch;ch = getchr();}sym.name[n] = '\0';sym.code = 33;}else {  // 判断特殊字符if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=' ||ch == '.' || ch == ',' || ch == ';' || ch == '(' || ch == ')') {str[0] = ch; str[1] = '\0';ch = getchr();for (i = 0;i < lenth2;i++) {if (!strcmp(str, d[i])) {strcpy(sym.name, str);sym.code = i + 16;break;}}}else if (ch == '#') {str[0] = ch; str[1] = '\0';ch = getchr();strcpy(sym.name, str);sym.code = 35;}else if (ch == '<') {char b = getchr();if (b == '>') {str[0] = '<';str[1] = '>';str[2] = '\0';strcpy(sym.name, str);sym.code = 21;ch = getchr();}else if (b == '=') {str[0] = '<';str[1] = '=';str[2] = '\0';strcpy(sym.name, str);sym.code = 23;ch = getchr();}else {str[0] = '<';str[1] = '\0';strcpy(sym.name, str);sym.code = 22;ch = b;}}else if (ch == '>') {char b = getchr();if (b == '=') {str[0] = '>';str[1] = '=';str[2] = '\0';strcpy(sym.name, str);sym.code = 25;ch = getchr();}else {str[0] = '>';str[1] = '\0';strcpy(sym.name, str);sym.code = 24;ch = b;}}else if (ch == ':') {char b = getchr();if (b == '=') {str[0] = ch;str[1] = b;str[2] = '\0';strcpy(sym.name, str);sym.code = 30;ch = getchr();}else {str[0] = ch;str[1] = '\0';strcpy(sym.name, str);sym.code = 29;ch = b;}}}
}char getchr() {  // 从文件中获取下一个非空字符char ch = fgetc(f1);if (ch == '\n') {row = 1;line++;}else {if (ch != ' ' && ch != '\t') {row++;}}return ch;
}void error(int n) {printf("There are %d-error\n", n);exit(0);
}void program() { // 程序proghead();block();cout<<sym.code<<" "<<sym.name<<endl;cout<<!feof(f1)<<endl;if (sym.code == DOT && feof(f1)) {return ;}else {error(2);}
}void proghead() { // 程序首部if (sym.code == PROGRAM) {getsym(); // 获取next tokenif (sym.code == ID) {getsym();if (sym.code == SEM)getsym();elseerror(5);}elseerror(4);}elseerror(3);
}void block() {  // 分程序consexpl();varexpl();procdefi();compsent();
}void consexpl() { // 常量说明部分if (sym.code == CONST) {getsym();consdefi();conssuff();if (sym.code == SEM)getsym();elseerror(6);} // 无else表示可以为空
}void consdefi() {   // 常量定义if (sym.code == ID) {getsym();if (sym.code == EQU) {getsym();if (sym.code == INT)getsym();elseerror(9);}elseerror(8);}elseerror(7);
}void conssuff() {  // 常量定义后缀if (sym.code == COM) {getsym();consdefi();conssuff();
//      if (sym.code == SEM)//        getsym();//else//error(10);}// 无else表示可以为空
}
void varexpl() {  // 变量说明部分if (sym.code == VAR) {getsym();vardefi();varsuff();}// 无else表示可以为空
}void vardefi() {  // 变量定义if (sym.code == ID) {getsym();idsuff();if (sym.code == COL) {getsym();typeil();if (sym.code == SEM)getsym();elseerror(12);}elseerror(11);}//    else//      error(10);
}void varsuff() {if (sym.code == ID) {vardefi();varsuff();}// 无else表示可以为空
}void typeil() {if (sym.code == INTEGER || sym.code == LONG)getsym();elseerror(13);
}void procdefi() {if (sym.code == PROCEDURE){procedh();block();if (sym.code == SEM) {procsuff();}elseerror(14);}// 无else表示可以为空
}void procedh() {if (sym.code == PROCEDURE) {getsym();if (sym.code == ID) {getsym();argument();if (sym.code == SEM)getsym();elseerror(16);}elseerror(15);}
}void argument() {if (sym.code == LBR) {getsym();if (sym.code == ID) {getsym();if (sym.code == COL) {getsym();if (sym.code == RBR)getsym();elseerror(19);}elseerror(18);}error(17);}
}void procsuff() {if (sym.code == PROCEDURE) {procedh();block();if (sym.code == SEM) {getsym();procsuff();}elseerror(20);}
}void assipro() {if (sym.code == ID) {getsym();suffix();}elseerror(21);
}void sentence() {if (sym.code == ID) {assipro();}else if (sym.code == IF) {ifsent();}else if (sym.code == WHILE)whilsent();else if (sym.code == READ)read();else if (sym.code == WRITE)write();else if (sym.code == BEGIN)compsent();
}void suffix() {if (sym.code == ASS) {getsym();express();}else if (sym.code == LBR) {getsym();express();if (sym.code == RBR)getsym();else error(22);}
}void ifsent() {if (sym.code == IF) {getsym();conditio();if (sym.code == THEN) {getsym();sentence();}elseerror(24);}elseerror(23);
}void whilsent() {if (sym.code == WHILE) {getsym();conditio();if (sym.code == DO) {getsym();sentence();}elseerror(26);}elseerror(25);
}void read() {if (sym.code == READ) {getsym();if (sym.code == LBR) {getsym();if (sym.code == ID) {getsym();idsuff();if (sym.code == RBR)getsym();else error(27);}elseerror(30);}else error(29);}else error(28);
}void idsuff() {if (sym.code == COM) {getsym();if (sym.code == ID) {getsym();idsuff();}elseerror(30);} // 无else表示可以为空
}void write() {if (sym.code == WRITE) {getsym();if (sym.code == LBR) {getsym();express();exprsuff();if (sym.code == RBR)getsym();else error(34);}else error(33);}else error(32);
}void compsent() {if (sym.code == BEGIN) {getsym();sentence();sentsuff();if (sym.code == END)getsym();else error(36);}else error(35);
}void exprsuff() {if (sym.code == COM) {getsym();express();exprsuff();}
}void sentsuff() {if (sym.code == SEM) {getsym();sentence();sentsuff();}
}void conditio() {if (sym.code == ODD) {getsym();express();}else {express();respoper();express();}
}void express() {if (sym.code == ADD || sym.code == SUB)getsym();term();termsuff();
}void term() {factor();factsuff();
}void termsuff() {if (sym.code == ADD || sym.code == SUB) {getsym();factor();factsuff();}
}void factsuff() {if (sym.code == MUL || sym.code == DIV) {getsym();factor();factsuff();}
}void factor() {if (sym.code == ID) {getsym();
//      factsuff();}else if (sym.code == INT) {getsym();}else if (sym.code == LBR) {getsym();express();if (sym.code == RBR)getsym();else error(38);}else error(37);
}void addoper() {if (sym.code == ADD || sym.code == SUB)getsym();elseerror(39);
}void muloper() {if (sym.code == MUL || sym.code == DIV)getsym();elseerror(40);
}void respoper() {if (sym.code >= EQU && sym.code <= GEQ)getsym();elseerror(41);
}

实验结果

待分析代码

program main;
const x = 1, y=2,z=444;
var z,x:long;xx:long;
a:long;
begin
z := z*3/2;
read(xx,dsaf);
write(dsaf,xx);
if x > y
then
x := x+1;
begin
x := x+1;
y:= xx -12;
x := +123;
x := (1+2);
x:= 213 * 3 + 21/x;
y := y/2 +2;
begin
while x<=10
do
y:=y+1;
end
end
end.

以上代码只是单纯为了检测是否能够通过语法分析,并没有什么实际含义(o゜▽゜)o


语法分析检测通过!

实验二 语法分析1——递归子程序法相关推荐

  1. 编译原理实验二:赋值语句的语法分析程序设计

    编译原理实验二:赋值语句的语法分析程序设计 1.1实验内容 目的: 在前面实验的基础上,通过设计.编制.调试一个典型的赋值语句的语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查,进一步掌握 ...

  2. 编译原理实验--实验二 递归下降法判断算术表达式的正确性--Python实现

    目录 一.实验目的和要求 二.实验内容 三.实验环境 四.实验步骤 1.语法分析所依据的文法: 2.给出消除左递归及提取左公因子的文法: 五.测试要求 六.实验步骤 1.语法分析所依据的文法 2.给出 ...

  3. python递归算法 电影院票价问题_算法课堂实验报告(二)——python递归和分治(第k小的数,大数乘法问题)...

    python实现递归和分治 一.开发环境 开发工具:jupyter notebook 并使用vscode,cmd命令行工具协助编程测试算法,并使用codeblocks辅助编写C++程序 编程语言:py ...

  4. 编译原理--实验2 语法分析

    文章目录 前言 1.1实验目的 1.2 实验任务 1.3 实验内容 1.3.1 实验要求 1.3.2 输入格式 1.3.3 输出格式 1.3.4 样例 1.4 程序 1.4.1 程序流程图 1.4.2 ...

  5. 20172305 2017-2018-2 《程序设计与数据结构》实验二报告

    20172305 2017-2018-2 <程序设计与数据结构>实验报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 谭鑫 学号:20172305 实验教师:王志强 ...

  6. 编译原理实验二:Bison

    编译原理实验二:Bison 实验要求 1.了解Bision基础知识,如何将文法产生式转换为Bison语句 2.阅读/src/common/SyntaxTree.c,对应头文件 /include/Syn ...

  7. 哈工大计算机系统实验二——DataLab数据表示

    计算机系统实验二特别难,和上一届的实验不一样,没有学长的火炬,当时做的时候特别崩溃.幸好有一帮志同道合的伙伴们,一起慢慢把实验解决了. 把火炬传下去! 实验报告 实 验(二) 题     目 Data ...

  8. 操作系统真象还原实验记录之实验二十三:硬盘分区,并编写硬盘驱动程序

    操作系统真象还原实验记录之实验二十三:编写硬盘驱动程序 1.硬盘分区 1.1 创建Seven80.img硬盘 ./bximage -mode=create -imgmode=flat -hd=80 - ...

  9. 机器学习实验二---决策树python

    机器学习实验二---决策树python 一.了解一下决策树吧 决策树基本流程 信息增益 决策树的优缺点 二.数据处理 三.决策树的构建 计算给定数据集的香农熵 按照给定特征划分数据集 选择最好的数据划 ...

  10. 数据结构实验二 :二叉树的操作与实现

    数据结构实验一:线性表,堆栈和队列实现 数据结构实验二 :二叉树的操作与实现 数据结构实验三: 图的操作与实现 数据结构实验四 : 查找和排序算法实现 文章目录 一.实验目的: 二.使用仪器.器材 三 ...

最新文章

  1. 分布式系统开发——调度技术
  2. Spring MVC Servlet XML文件配置
  3. 用c语言编辑一个通讯录,C语言实现一个通讯录
  4. AWR 报告深度解读:Time Model Statistics 信息的计算和获取
  5. 二叉搜索树的2层结点统计_植树节,程序猿种的那些树
  6. STM8单片机 ADC模拟看门狗中文资料错误
  7. 蓝桥杯 ADV-224 算法提高 9-1九宫格
  8. Shell脚本编程之(四)善用判断式
  9. Kubernetes集群管理部署
  10. C#通过NOPI读写Excel,并插入图片,VS2019
  11. 基于 Elasticsearch 存储的HBase二级索引方案
  12. 【深度学习技术】小样本医学影像的深度学习关键技术之深度模型的可解释性
  13. 中国四大资产管理公司 ACM
  14. php中文数组,php数组的定义
  15. 修改360抢票的刷新频率+突破8车次限制,太简单了
  16. Python调用百度API实现语音识别
  17. MySQL Workbench报错说 seems to be a different OS
  18. echarts 日历图
  19. 回字的四种写法之编程
  20. discus 怎么添加门户功能

热门文章

  1. 计算机数据链路层教案,4.1数据链路层作用教案(计算机网络技术基础教案).doc...
  2. 常见的DoS攻击防御方式
  3. C语言随机数10到999990,C语言程序设计(高清pdf) 丹尼斯 里奇
  4. 服务器ftp查看文件,ftp命令查看文件列表 - 卡饭网
  5. 皮尔逊相关系数_SPSS篇——皮尔逊相关
  6. 这几天阅读的shadowgun的几个shader
  7. PHP连接MySQL 8.0报错的解决办法
  8. windows 2008下载地址及版本介绍
  9. python粒子群喷发_python3实现单目标粒子群算法
  10. 锐捷交换机端口设置trunk模式并指定允许的vlan数据包通过