实验类型: 设计性 实验学时:4 实验要求:必修
一、实验目的
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
二、实验内容
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1 待分析的简单语言的语法
用扩充的范式表示如下:

2.2 实验要求说明
输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
例如:
输入 begin a:=9; x:=2*3; b:=a+x end #
输出 success!
输入 x:=a+b*c end #
输出 error
三、仪器设备
计算机,C++6.0软件环境。
四、所需耗材
无
五、实验原理、方法和手段
语法分析程序的算法思想
(1)主程序示意图如图5-1所示。

(2)递归下降分析程序示意图如图5-2所示。
(3)语句串分析过程示意图如图5-3所示。

(4)statement语句分析程序流程如图5-4、5-5、5-6、5-7所示。

六、实验步骤
阅读实验说明,做好实验准备,然后进行编辑调试。
七、实验结果处理
演示结果并保存相关文件。
八、实验注意事项
注意数据输入格式,单词的匹配规则。
九、预习与思考题
预习:阅读课本相关内容,分析相关算法设计思想,熟悉VC++6.0使用方式。
思考题:类C语言程序的语法分析。
十、实验报告要求
1、实验报告中应包括相关操作步骤和程序代码。
2.书写实验报告时要结构合理,层次分明,在分析描述的时候,需要注意语言的流畅。
准备工作

代码
#include<iostream>
#include<string>
#include<fstream>
#include<windows.h>
using namespace std;
//自定义定义两个改变字体颜色函数
void SetFontRed(){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
}
void SetFontWhite(){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}
/*词法分析器*/
#define MAXROW 100//源代码的最大行数
#define MAXTABLE 1000//符号表和常数表最大存储范围
string ReservedWordList[6]={"begin","if","then","while","do","end"};//关键字表
//声明全局变量
string ScanBuffer[MAXROW];//扫描缓冲区,定义为字符串数组
struct SymbolTable{
int code;
string symbol;
}ST[MAXTABLE];//符号表
struct ConstantTable{
int code;
int constant;
}CT[MAXTABLE];//常数表
int STi=0,CTi=0;//符号表和常数表指示器
struct Word{
int code;
string symbol;
int constant;
}word;
int row=0,col=0;//搜索指示器,row指行,col指列
int endrow;
char ch;//搜索指示器指示的当前字符
string strToken;//当前字符串
//声明全局函数
void Input();//子程序过程,将源代码输入进扫描缓冲区
void GetChar();//子过程程序,将下一输入字符读到ch中,搜索指示器前移一字符位置
void GetDel();//子程序过程,检查ch中的字符是否为分隔符。若是,则调用GetChar直至ch中进入一个非分隔符(delimiters->分隔符)
void Concat();//子程序过程,,将ch中的字符连接到strToken之后
bool IsLetter();//布尔函数过程,判断ch中的字符是否为字母
bool IsDigit();//布尔函数构成,判断ch中的字符是否为数字
int Reserve();//整型函数过程,对strToken中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0值(假定0不是保留字的编码)
void Retract();//子程序过程,将搜索指示器回调一个字符位置,将ch置为空白字符
int InsertID();//整型函数过程,将strToken中的标识符插入符号表,返回符号表指针
int InsertConst();//整型函数过程,将strToken中的常数插入常数表,返回常数表指针
void LexicalAnalyzerProcError();//子程序过程,词法分析出错,提示错误信息
//定义函数
void Input(){
int op;
cout<<"请输入数字选择输入格式"<<endl;
cout<<"1,键盘输入"<<endl<<"2,文件输入"<<endl;
cin>>op;
int i=0;
char c;//输入流中的当前字符
if(op==1){
while((c=cin.get())!=EOF){
ScanBuffer[i].push_back(c);
if(c=='\n') i++;
}
endrow=--i;
}
else{
fstream in;
in.open("test.txt",ios::in);
while(in.peek()!=EOF){
c=in.get();
ScanBuffer[i].push_back(c);
if(c=='\n') i++;
}
endrow=--i;
}
}
void GetChar(){
ch=ScanBuffer[row][col];
col++;
}
void GetDel(){
while(ch=='\n'){
row++;
col=0;
GetChar();
}
while(ch==' '||ch=='\t') GetChar();
}
void Concat(){
strToken.push_back(ch);
}
bool IsLetter(){
return isalpha(ch);
}
bool IsDigit(){
return isdigit(ch);
}
int Reserve(){
int i;
for(i=0;i<6;i++)
if(ReservedWordList[i]==strToken) return i+1;
return 10;
}
void Retract(){
col--;
ch='\0';
}
void LexicalAnalyzerProcError(){
SetFontRed();
cout<<"[Error]"<<row<<" row"<<','<<col<<" col"<<endl;
SetFontWhite();
}
struct Word LexicalAnalyzer(){//结构体函数,向语法分析器返回一个单词的种别码和值
if(row!=endrow||ScanBuffer[row][col]!='\n'){
int code,value;
strToken="";
GetChar();
GetDel();
if(IsLetter()){
while(IsLetter()||IsDigit()){
Concat();
GetChar();
}
Retract();
code=Reserve();
if(code!=10){
//value=InsertID(strToken);
ST[STi].code=word.code=code;
ST[STi].symbol=word.symbol=strToken;
STi++;
return word;
//cout<<'('<<code<<','<<strToken<<')'<<endl;
//return (code,value);
}
else{
ST[STi].code=word.code=code;
ST[STi].symbol=word.symbol=strToken;
STi++;
return word;
//cout<<'('<<code<<','<<strToken<<')'<<endl;
//return (code,-);
}
}
else if(IsDigit()){
while(IsDigit()){
Concat();
GetChar();
}
Retract();
//value=InsertConst();
CT[CTi].code=word.code=11;
CT[CTi].constant=word.constant=stoi(strToken);
CTi++;
return word;
//cout<<'('<<11<<','<<strToken<<')'<<endl;
//return ($INT,value);
}
else if(ch=='+'){
word.code=13;
word.symbol="+";
return word;
//return (13,-);
//cout<<"(13,+)"<<endl;
}
else if(ch=='-'){
word.code=14;
word.symbol="-";
return word;
//return (14,-);
//cout<<"(14,-)"<<endl;
}
else if(ch=='*'){
word.code=15;
word.symbol="*";
return word;
//return (15,-);
//cout<<"(15,*)"<<endl;
}
else if(ch=='/'){
word.code=16;
word.symbol="/";
return word;
//return (16,-);
//cout<<"(16,/)"<<endl;
}
else if(ch==':'){
GetChar();
if(ch=='='){
word.code=18;
word.symbol=":=";
return word;
//return (18,-);
//cout<<"(18,:=)"<<endl;
}
else{
Retract();
word.code=17;
word.symbol=":";
return word;
//return (17,-);
//cout<<"(17,:)"<<endl;
}
}
else if(ch=='<'){
GetChar();
if(ch=='>'){
word.code=21;
word.symbol="<>";
return word;
//return (21,-);
//cout<<"(21,<>)"<<endl;
}
else if(ch=='='){
word.code=22;
word.symbol="<=";
return word;
//return (22,-);
//cout<<"(22,<=)"<<endl;
}
else{
Retract();
word.code=20;
word.symbol="<";
return word;
//return (20,-);
//cout<<"(20,<)"<<endl;
}
}
else if(ch=='>'){
GetChar();
if(ch=='='){
word.code=24;
word.symbol=">=";
return word;
//return (24,-);
//cout<<"(24,>=)"<<endl;
}
else{
Retract();
word.code=23;
word.symbol=">";
return word;
//return (23,-);
//cout<<"(23,>)"<<endl;
}
}
else if(ch=='='){
word.code=25;
word.symbol="=";
return word;
//return (25,-);
//cout<<"(25,=)"<<endl;
}
else if(ch==';'){
word.code=26;
word.symbol=";";
return word;
//return (26,-);
//cout<<"(26,;)"<<endl;
}
else if(ch=='('){
word.code=27;
word.symbol="(";
return word;
//return (27,-);
//cout<<"(27,()"<<endl;
}
else if(ch==')'){
word.code=28;
word.symbol=")";
return word;
//return (28,-);
//cout<<"(28,))"<<endl;
}
else if(ch=='#'){
word.code=0;
word.symbol="#";
return word;
//return (0,-);
//cout<<"(0,#)"<<endl;
}
else LexicalAnalyzerProcError();
}
}
/*词法分析器*/
//////////////////////////////////////////////////////////////////////////////////////////////////
/*语法分析器*/
//声明递归下降分析程序的子程序
void Parser();//语法分析器总控程序
void ADVANCE();//把输入串指示器IP指向下一个输入符号
void ParserProcError();//语法分析器的出错处理子程序
void P();//非终结符P的分析子程序
void S();//非终结符S的分析子程序
void S1();//非终结符S'的分析子程序
void S2();//非终结符S"的分析子程序
void A();//非终结符A的分析子程序
void E();//非终结符E的分析子程序
void E1();//非终结符E'的分析子程序
void T();//非终结符T的分析子程序
void T1();//非终结符T'的分析子程序
void F();//非终结符F的分析子程序
//声明递归下降分析程序的全局变量
struct Word IP;//输入串指示器,指示当前扫描器扫描出的单词在表中的地址
struct Word SYM;//IP当前所指的那个输入符号
//定义函数
void ADVANCE(){
IP=SYM=LexicalAnalyzer();
}
void ParserProcError(int op){
SetFontRed();
cout<<"[Error]"<<row<<" row"<<'\t';
switch(op){
case 1:if(SYM.code==11) cout<<"expect \'begin\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \'begin\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
case 2:if(SYM.code==11) cout<<"expect \'end\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \'end\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
case 3:if(SYM.code==11) cout<<"expect \'id\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \'id\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
case 4:if(SYM.code==11) cout<<"expect \':=\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \':=\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
case 5:if(SYM.code==11) cout<<"expect \'id|num|(\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \'id|num|(\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
case 6:if(SYM.code==11) cout<<"expect \')\' before "<<'\''<<SYM.constant<<'\''<<endl;
else cout<<"expect \')\' before "<<'\''<<SYM.symbol<<'\''<<endl;
break;
}
SetFontWhite();
}
/*
单词符号 种别码 单词符号 种别码
begin 1 : 17
if 2 := 18
then 3 < 20
while 4 <> 21
do 5 <= 22
end 6 > 23
id 10 >= 24
num 11 = 25
+ 13 ; 26
- 14 ( 27
* 15 ) 28
/ 16 # 0
*/
void P(){
if(SYM.code==1){
ADVANCE();
S();
if(SYM.code==6){
ADVANCE();
if(SYM.code==0){
cout<<"语法正确"<<endl;
return ;
}
}
else ParserProcError(2);//没有end
}
else ParserProcError(1);//没有begin
}
void S(){
S1();
S2();
}
void S1(){
A();
}
void S2(){
if(SYM.code==26){
ADVANCE();
S1();
S2();
}
}
void A(){
if(SYM.code==10){
ADVANCE();
if(SYM.code==18){
ADVANCE();
E();
}
else ParserProcError(4);//当前单词不是:=
}
else ParserProcError(3);//当前单词不是id
}
void E(){
T();
E1();
}
void E1(){
if(SYM.code==13||SYM.code==14){
ADVANCE();
T();
E1();
}
}
void T(){
F();
T1();
}
void T1(){
if(SYM.code==15||SYM.code==16){
ADVANCE();
F();
T1();
}
}
void F(){
if(SYM.code==10) ADVANCE();
else if(SYM.code==11) ADVANCE();
else if(SYM.code==27){
ADVANCE();
E();
if(SYM.code==28) ADVANCE();
else ParserProcError(6);//')'不匹配
}
else ParserProcError(5);//既不是id,也不是num,更不是'('
}
void Parser(){
SetFontWhite();
Input();
ADVANCE();
P();
}
int main(){
Parser();
return 0;
}
本次实验要求设计并实现一个递归下降分析器,用于对简单语言的词法序列进行语法检查和结构分析。实验内容包括利用C语言编写程序,处理以“#”结束的输入单词串,正确则输出“success”,错误则输出“error”。实验还包括理解并应用语法分析程序的算法思想,以及编写相关程序流程。实验报告需包含操作步骤、程序代码和问题思考。

8929

被折叠的 条评论
为什么被折叠?



