1 实验内容
完成以下描述赋值语句的 LL(1)文法的递归下降分析程序
G[S]: S→ V=E
E→ TE’
E’→ ATE’ | e
T→ FT’
T’→ MFT’ | E
F→ (E) | i
A→ + | -
M→ * | /
V→ i
设计说明:终结符号 i 为用户定义的简单变量,即标识符的定义。
2 实验要求
(1)输入串应是词法分析的输出二元式序列,即某算术表达式“专题 1” 的输出结果,输出为输入串是否为该文法定义的算术表达式的判断结果;
(2)递归下降分析程序应能发现简单的语法错误;
(3)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;
(4)选做:如有可能,考虑如何用文法描述 C 语言的 if 语句,使整个文 法仍然为 LL(1)文法,并使得你的递归下降程序可以分析赋值语句和 if 语句
3.程序功能描述
结合实验要求,完成实验二程序,具体实现功能为读取同目录下的实验一输出的词法判别的二元式文件,根据给定文法,按照递归下降分析的方式判断输入的语句是否合理。对于不合理的部分,在判定出错之后输出错误的点。
4.程序结构描述
由于语法是给定的,所以可以先完成first和follow集合的计算:
根据first和follow集合以及给定的文法,可以确定递归向下分析程序的结构。
所以程序的整体表达式结构为:
S的递归分析程序结构如下图
E的递归下降分析程序结构如下图:
E’的递归向下分析的结构图
T的递归下降分析程序结构如下:
T’的递归下降分析程序结构如下:
F的递归下降分析程序结构如下:
A的递归下降分析程序结构如下:
M的递归下降分析程序结构如下:
V的递归下降分析程序结构如下:
5.实现代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include <cassert>
#include<fstream>
#define MAX_LINE 1024
using namespace std;// 函数声明
void S();
void E();
void E_();
void T();
void T_();
void F();
void A();
void M();
void V(); // 定义一个长度为100的字符数组
char s[100];// 用来作数组索引,当每次匹配成功存入数据时index自增1
int i;
// 用来标记语句是否正确
int SIGN;int main()
{
// printf("请输入你的语句(记得在最后带上#)\n");cout<<"读取文件可知输入语句:"<<endl;FILE *fp;char buf[MAX_LINE];string shizi,like;if((fp = fopen("text.txt","r"))!=NULL){while(fgets(buf,MAX_LINE,fp) != NULL){int len = strlen(buf);buf[len-1] = '\0'; /*去掉换行符*/printf("%s \n",buf);int flag=0;if(buf[1]=='1'){like+='i';}for(int i=0;i<len;i++){if(buf[i]=='"'&&flag==0){i++;while(buf[i]!='"'){shizi+=buf[i];if(buf[1]!='1'){like+=buf[i];}i++;}}}}}shizi+='#';like+='#';fclose(fp);cout<<"输入的语句为:"<<shizi<<endl;cout<<"可以理解为:"<<like<<endl;SIGN = 0;//语句是否正确用SIGNi=0;//将输入的式子按照修改为字符串格式char* int length=like.length();for(int i=0;i<length;i++){s[i]=like[i];}// 当输入的第一个字符为#时,程序直接结束if( s[0] == '#')return 0;S();// 如果最后的字符以#结束则输出下面if(s[i]=='#'&&SIGN==0){printf("\n语句合法\n");}else{printf("\n语句不合法\n");}
// printf("请输入你的语句(记得在最后带上#)\n");
// }return 1;
}void S()
{if(SIGN==0){printf("S检查 ");// 当输入的字符串中首字母为a时if(s[i]=='i'){V();if(SIGN==0&&s[i]=='='){
// printf("(%c) ",s[i]);i++;E();}else{SIGN=1;cout<<"S处出现错误"<<endl; }} else{SIGN=1;cout<<"S处出现错误"<<endl; }}
}void E()
{if(SIGN==0){printf("E ");if(s[i]=='('||s[i]=='i'){T();if(SIGN==0){if(s[i]=='+'||s[i]=='-'){E_();} else if(s[i]==')'||s[i]=='#'){return;}else{SIGN=1;cout<<"E处出现错误"<<endl; }} }else{SIGN=1;cout<<"E处出现错误"<<endl; }}
}void E_()
{if(SIGN==0){printf("E' ");if(s[i]=='+'||s[i]=='-'){A();if(SIGN==0){if(s[i]=='('||s[i]=='i'){T();if(SIGN==0){if(s[i]=='+'||s[i]=='-'){E_();} else if(s[i]==')'||s[i]=='#') {return;}else{SIGN=1;cout<<"E'处出现错误"<<endl; }}}else{SIGN=1;cout<<"E'处出现错误"<<endl; }}}else if(s[i]==')'||s[i]=='#'){return;}else{SIGN=1;cout<<"E'处出现错误"<<endl; }}
}void T()
{if(SIGN==0){printf("T ");if(s[i]=='('||s[i]=='i'){F();if(SIGN==0){if(s[i]=='*'||s[i]=='/'){T_();}else if(s[i]=='+'||s[i]=='-'||s[i]==')'||s[i]=='#') {return;}else{SIGN=1;cout<<"T处出现错误"<<endl; }}}else{SIGN=1;cout<<"T处出现错误"<<endl; }}
}void T_()
{if(SIGN==0){printf("T' ");if(s[i]=='*'||s[i]=='/'){M();if(SIGN==0){F();if(SIGN==0){T_();}}}else if(s[i]=='+'||s[i]=='-'||s[i]==')'||s[i]=='#'){return; }else{SIGN=1;cout<<"T'处出现错误"<<endl; }}
}void F()
{if(SIGN==0){printf("F ");if(s[i]=='('){
// printf("(%c) ",s[i]);i++;if(s[i]=='('||s[i]=='i'){E();if(SIGN==0){if(s[i]==')'){
// printf("(%c) ",s[i]);i++;}else{SIGN=1;cout<<"F处出现错误"<<endl; }}}else{SIGN=1;cout<<"F处出现错误"<<endl; }}else if(s[i]=='i'){
// printf("(%c) ",s[i]);i++;}else{SIGN=1;cout<<"F处出现错误"<<endl; }}
}void A()
{if(SIGN==0){printf("A ");if(s[i]=='+'||s[i]=='-'){
// printf("(%c) ",s[i]);i++;}else{SIGN=1;cout<<"A处出现错误"<<endl; }}
}void M()
{if(SIGN==0){printf("M ");if(s[i]=='*'||s[i]=='/'){
// printf("(%c) ",s[i]);i++;}else{SIGN=1;cout<<"M处出现错误"<<endl; }}
}void V()
{if(SIGN==0){printf("V ");if(s[i]=='i'){
// printf("(%c) ",s[i]);i++;}else{SIGN=1;cout<<"V处出现错误"<<endl; }}
}
6.程序测试
按照实验要求,提供两个测试样例,一个正确一个错误:
首先是正确的测试样例,将a=b*(c+d)输入在input文件中,启动程序lab1,产生对应的二元式,这里为了便于判断和操作,将标识符的二元式输出修改为(1,‘符号’),得到的输出二元式如下:
接下来启动Lab2,可以得到如下结果:
将上图的输出部分单独显示:
读取文件可知输入语句:
(1,“a”)
(运算符,“=”)
(1,“b”)
(运算符,"“)
(分隔符,”(“)
(1,“c”)
(运算符,”+“)
(1,“d”)
(分隔符,”)")
输入的语句为:a=b(c+d)#
可以理解为:i=i*(i+i)#
S检查 V E T F T’ M F E T F E’ A T F T’
语句合法
其中倒数第二行的输出是进行递归下降分析的过程中,每一个非终结符号对应函数的使用的输出。
接下来是错误的测试样例:将a=b*(c+d输入在input文件中,启动程序lab1,产生对应的二元式,得到的输出二元式如下:
启动Lab2的程序之后得到的结果如下:
将程序输出部分单独显示:
读取文件可知输入语句:
(1,“a”)
(运算符,“=”)
(1,“b”)
(运算符,"“)
(分隔符,”(“)
(1,“c”)
(运算符,”+")
(1,“d”)
输入的语句为:a=b(c+d#
可以理解为:i=i*(i+i#
S检查 V E T F T’ M F E T F E’ A T F
F处出现错误
语句不合法