老师要求做的一个课设,但是。网上很多都不是递归下降的。
在理解编译原理基本思想的基础上,选择一个自己熟悉的程序设计语言,完成编译程序的设计和实现过程。
编译程序的设计可以采用自顶向下和自底向上两种不同的方法。由于许多高级语言(如PASCAL,C)中的语法成分都是递归定义的,所以本实验要求学生采用递归下降分析技术,这是一种自顶向下的的编译方法,其基本思想是对语言的每个(或若干个)语法成分编制一个处理子程序,从处理<程序>这个语法成分的子程序开始,在分析过程中调用一系列过程或函数,对源程序进行语法和语义分析,直到整个源程序处理完毕为止。
本上机实习是为C语言(子集)设计一个编译程序,完成词法分析、语法分析、语义分析等功能,并生成某种机器上的目标代码(汇编语言)或中间代码(四元式)。
这是老师的要求2、C语言小子集的文法规则:
<程序>::=main(){<分程序>}
<分程序>::=<变量说明部分>;<语句部分>
<变量说明部分>::=<变量说明><标识符表>
<变量说明>::=int
<标识符表>::=<标识符表>,<标识符>
<标识符表>::=<标识符>
<标识符>::=<字母>
<标识符>::=<标识符><字母>
<标识符>::=<标识符><数字>
<语句部分>::=<语句部分><语句>;|<语句>;
<语句>::=<赋值语句>|<条件语句>|<循环语句>|
<赋值语句>::=<标识符>=<表达式>
<条件>::=<表达式><关系运算符><表达式>
<表达式>::=<项>|<表达式><加法运算符><项>
<项>::=<因子>|<项><乘法运算符><因子>
<因子>::=<标识符>|<常量>|(<表达式>)
<常量>::=<无符号整数>
<无符号整数>::=<数字序列>
<数字序列>::=<数字序列><数字>
<数字序列>::=<数字>
<加法运算符>::=+|-
<乘法运算符>::=*|/
<关系运算符>::=<|>|!=|>=|<=|==
<复合语句>::={<语句部分>}
<语句1>::=<语句>|<复合语句>
<条件语句>::=if(<条件>)<语句1>else<语句1>
<循环语句>::=while(<条件>)do<语句1>
<字母>::=a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z
<数字>::=0|1|2|3|4|5|6|7|8|9
输入源程序样本:(这只是一个例子,调试时可以任意修改或换其它程序)
main (){ int a,x,b,y,max;
a=10; b=12;
while (a<0)
{ b=a+b*a;
a=a-1
};
x=a+b; y=b+b;
if (x>y) max=x;
else max=y;
}
下面直接给代码(代码有点长,700行左右)
#include<stdio.h>
#include<sstream>
#include<iostream>
#include<stdlib.h>
#include<fstream>
#include<string.h>
#include<math.h>
#include<cstring>
#include <vector>
#include<iomanip>
using namespace std;
char const *keyword[7] = { "if", "else", "for", "while", "do", "int", "main"}; //关键字
class Word //单词表类
{
public:
char value[20];//单词自身的值
int type;//单词的种别(10标识符,20常数,30关键字,4-运算符(加法运算符为41,乘法为42,关系运算符43),50界符)
int line;//行号
};
class Genq //四元式
{
public:
string op; //算符
string data1;//操作数1
string data2;//操作数2
string res; //结果
};
FILE *fin,*fout;//文件流
int line=1; //单词所在行数
char buff[10];//存放单词的数组
int flag=0;//词法分析判断是否已经从文件流中获取字符
Word new_w;
Genq four[100];//用数组表示类对象四元式
int f_num=0;//四元式个数
int e;//错误次数
char ch;//字符流中获取的字符
int flag1,flag2=0;
string ys[100];//已经声明的变量
int y_num=0;//已经声明变量的个数
string op; //算符
string str1;//操作数1
string str2;//操作数2
string result; //结果
int f=0; //表达式中运算符的个数
int aaa;
int tj_x;//记录while和if条件的四元式的序号
string a[200];
string a2;
string a3;
int a_num=1;
void P();//程序
int A(); //(){分程序}
void B();//分程序
void C();//变量说明部分
int F();//标识符表
int F1();//标识符
void D();//语句部分
int D1();//子语句部分
int H();//语句
int I();//赋值语句
int Q();//表达式
int X();//项
int X1();//子项
int Q1(); //子表达式
int Y();//因子
int J();//条件语句
void K();//循环语句
int H1();//语句1
int TJ();//条件
void makeFour(string op,string d1,string d2,string r)//构造四元式
{
four[f_num].op=op;
four[f_num].data1=d1;
four[f_num].data2=d2;
four[f_num].res=r;
f_num++;
}
void printFour()//输出四元式
{
ofstream out("ygro.txt");
int i;
for(i=0;i<f_num;i++)
{
cout<<i<<":\t("<<four[i].op<<",\t"<<four[i].data1<<",\t"<<four[i].data2<<",\t"<<four[i].res<<")"<<endl;
out<<i<<":\t("<<four[i].op<<",\t"<<four[i].data1<<",\t"<<four[i].data2<<",\t"<<four[i].res<<")"<<endl;
}
}
void error(char doc[])//报错,定位到错误行
{
cout<<"第"<<new_w.line<<"行出错!\t";
cout<<doc<<"\n";
e++;
}
void ise(string a) //检查变量是否被声明
{
int i;
for(i=1;i<=y_num;i++)
{
if(a.compare(ys[i])==0)
{
break;
}
}
if(i>y_num)
{
cout<<"第 "<<new_w.line<<" 行出错!\t";
cout<<new_w.value<<" 没有被声明 !"<<endl;
e++;
}
}
int getWord()//词法分析
{
int i=0; //buff当前字符的位置
int j=0; //new_w当前字符的位置
if(flag==0)
{
ch=getc(fin);
}
while(ch==' '||ch=='\n'||ch=='\t')//识别空格,换行,和tab
{
if(ch=='\n')
{
line++;//行+1
}
ch=getc(fin);
flag=1;
}
if(ch>='a'&&ch<='z')//识别字母开头的变量或者单词;
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}i=0;
do{
buff[i++]=ch; //吧字符流中的字符放到buff中
ch=getc(fin);
flag=1;
}while((ch>='a' && ch<='z') || (ch>='0' && ch<='9'));
strcpy(new_w.value,buff);//把buff的值放到单词表
new_w.line=line;//行数
int n;
for(n=0;n<7;n++)
{
if(strcmp(new_w.value,keyword[n])==0)//判断是不是关键字
break;
}
if(n<7)//是关键字
{
new_w.type=30;//关键字类型为03
}else{
new_w.type=10;//标识符类型为01
}
return 0;
}
else if(ch>='0' && ch<='9')
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}i=0;
do{
buff[i++]=ch;
ch=getc(fin);
flag=1;
}while(ch>='0' && ch<='9');
strcpy(new_w.value,buff);
new_w.type=20;//数字类型为02
new_w.line=line;
//***************************
// cout<<new_w.value;
return 0;
}
else if(ch=='+' || ch=='-')
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}i=0;
buff[i++]=ch;
ch=getc(fin);
flag=1;
strcpy(new_w.value,buff);
new_w.type=41; //加法运算符
new_w.line=line;
//**************************
// cout<<new_w.value;
return 0;
}
else if(ch=='*'||ch=='/')
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}i=0;
buff[i++]=ch;
ch=getc(fin);
flag=1;
strcpy(new_w.value,buff);
new_w.type=42; //乘法运算符
new_w.line=line;
//**************************
// cout<<new_w.value;
return 0;
}
else if(ch=='='||ch=='<'||ch=='>'||ch=='!')
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}
i=0;
buff[i++]=ch;
ch=getc(fin);
flag=1;
if(ch=='=')
{
buff[i++]=ch;
ch=getc(fin);
flag=1;
}
strcpy(new_w.value,buff);
new_w.type=43; //关系运算符
new_w.line=line;
//**************************
// cout<<new_w.value;
return 0;
}
else if(ch==','||ch==';'||ch=='('||ch==')'||ch=='{'||ch=='}')
{
for(i=0;i<10;i++)
{
buff[i]=NULL;
}
i=0;
buff[i++]=ch;
strcpy(new_w.value,buff);
new_w.type=50;//界符
ch=getc(fin);
flag=1;
//**************************
//cout<<new_w.value;
return 0;
}
else
{
new_w.type=00;//错误的单词类型
strcat(new_w.value," ");
//*************************
//cout<<new_w.value;
return 0;
}
}
void P()//程序
{
getWord();//main
if(strcmp(new_w.value,"main"))//当new_w.value不等于main满足条件
{
error("缺少main");
}
getWord();//(
A();
}
int A() //(){分程序}
{
if(strcmp(new_w.value,"("))
{ error("缺少'('");}
getWord();//)
if(strcmp(new_w.value,")"))
{ error("缺少')'");}
getWord();//{
if(strcmp(new_w.value,"{"))
{ error("缺少'{'");}
getWord();//int
B();
//getWord();
if(strcmp(new_w.value,"} "))
{ error("缺少'}'");}
op="go";
str1="";
str2="";
result="";
makeFour(op,str1,str2,result);
cout<<"语法检查完成,共发现"<<e<<"个错误。"<<endl;
return 0;
}
void B()//分程序
{
C();
if(strcmp(new_w.value,";"))
{ error("缺少';'");}
getWord();//a=10;中的a
D();
}
void C()//变量说明部分
{
if(strcmp(new_w.value,"int"))
{ error("缺少'int'");}
getWord();//a
ys[++y_num]=new_w.value;
F();
}
int F()//标识符表
{
if(new_w.type==10)
{
getWord();
}
F1();//标识符表,标识符
return 0;
}
int F1()//标识符
{
if(strcmp(new_w.value,";")==0)
{
return 0;
}
if(strcmp(new_w.value,","))
{error("标识符错误");}
getWord();//b
ys[++y_num]=new_w.value;
if(new_w.type!=10)
{error("标识符错误");}
getWord();
F1();
return 0;
}
//***********************************
void D()//语句部分
{
H();//语句
D1();//子语句部分
}
int D1()//子语句部分
{
if(strcmp(new_w.value,"}")==0)
{
getWord();
if(strcmp(new_w.value,";")==0)
{
return 0;
}
else{
H();
D1();
return 0;
}
}
if(strcmp(new_w.value,";")==0)
{
getWord();
H();
D1();
}//else error("语句错误");
return 0;
}
int H()//语句
{/*
for(int i=0;i<100;i++)
{
strcpy(b[i].bds,"???");
}
int b_num=0;*/
if(new_w.type==10)//如果当前符号为标识符,则为赋值语句
{
f=0; //运算符的个数
flag2=0;
ise(new_w.value);//判断标识符是否定义
result=new_w.value;
//strcpy(b[b_num++].bds,new_w.value);//吧等号左边的值存入数组
getWord();
op=new_w.value;//op="="
// strcpy(b[b_num++].bds,new_w.value);
a[a_num++]=new_w.value;//=号
I();//赋值语句
makeFour(op,str1,str2,result);
return 0;
}
else if(strcmp(new_w.value,"if")==0)//判断是否为条件语句
{
flag2=0;
getWord();
J();//条件语句
return 0;
}
else if(strcmp(new_w.value,"while")==0)//判断为循环语句
{
aaa=f_num;
flag2=1;
getWord();
K();//循环语句
op="go";
str1="";
str2="";
stringstream ss;
ss<<aaa;
ss>>result;
makeFour(op,str1,str2,result);
//修改while跳转到的序号
stringstream ws;
ws<<f_num;
ws>>four[tj_x].res;
return 0;
}
else if(strcmp(new_w.value,";")==0)
{
return 0;
}
return 0;
}
int I()//赋值语句
{
if(strcmp(new_w.value,"="))
{error("缺乏'='");}
getWord();
str1=new_w.value;//str1=a a+b*a中的a
//strcpy(b[b_num++].bds,new_w.value);
Q();//表达式
return 0;
}
int Q()//表达式
{
X();//项
Q1();//子表达式
return 0;
}
int X()//项
{
Y();//因子
X1();//子项
return 0;
}
int X1()//子项
{
flag1=0;
if(strcmp(new_w.value,";")==0 || new_w.type==43||strcmp(new_w.value,")")==0)//当下一个字符为;或者关系运算符时,表达式结束
{
return 0;
}
else if(new_w.type!=41&&new_w.type!=42&&new_w.type!=43&&strcmp(new_w.value,",")!=0 )
{
flag1=1;
error("缺少';'");
return 0;
}
if(new_w.type==41||new_w.type==42)//加法.乘法运算符
{
f++;//运算符加一
if(f>1)
{
str1=str2;
result="temp"+f;
}
op=new_w.value;
}
getWord();
//strcpy(b[b_num++].bds,new_w.value);
Y();
return 0;
}
int Q1() //子表达式
{
if(strcmp(new_w.value,";")==0 || new_w.type==43||strcmp(new_w.value,")")==0)//当下一个字符为;或者关系运算符时,表达式结束
{
return 0;
}
else if(new_w.type!=41&&new_w.type!=42&&new_w.type!=43&&strcmp(new_w.value,",")!=0)
{
if(flag1==0){
error("缺少';'");
}
return 0;
}
if(new_w.type==41||new_w.type==42)//加法.乘法运算符
{
f++;//运算符加一
if(f>1)
{
str1=str2;
result="temp";
}
op=new_w.value;
}
getWord();
//strcpy(b[b_num++].bds,new_w.value);
X();
return 0;
}
int Y()//因子
{
if(new_w.type!=10 && new_w.type!=20 && strcmp(new_w.value,"("))
{
error("表达式错误!!!!");
return 0;
}
if(new_w.type==10||new_w.type== 20)//标识符和数字
{
if(op.compare("+")==0 || op.compare("-")==0 || op.compare("*")==0 || op.compare("/")==0)
{
str2=new_w.value;
if(result=="temp")
{
makeFour(op,str1,str2,result);
str2="temp";
result="b";
str1="a";//***************
op="+";//*********************
}
}
if(new_w.type==10)
{
ise(new_w.value);
}
getWord();//a-1 zhong de -
// strcpy(b[b_num++].bds,new_w.value);
a[a_num++]=new_w.value;
return 0;
}
else if(strcmp(new_w.value,"(")==0)
{
getWord();
Q();
if(strcmp(new_w.value,")")==0)
{
return 0;
}
}
return 0;
}
int J()//条件语句
{
if(strcmp(new_w.value,"("))
{
error("缺少'('");
}
getWord();
str1=new_w.value;
TJ();//条件
makeFour(op,str1,str2,result);
if(strcmp(new_w.value,")"))
{
error("缺少')'");
}
//使四元式为空
op="";
str1="";
str2="";
result="";
getWord();
H1();//语句一
if(strcmp(new_w.value,";")==0)
{
getWord();
}
stringstream if_s;//
if_s<<f_num+1;// int转string
if_s>>four[tj_x].res;//
tj_x=f_num;
op="go";
str1="";
str2="";
result="";
makeFour(op,str1,str2,result);//满足if条件之后 ,跳过else语句
if(strcmp(new_w.value,"else"))
{
error("缺少'else'");
H1();//语句一
}
else
{
getWord();
H1();//语句一
}
stringstream else_s;//
else_s<<f_num;// int转string
else_s>>four[tj_x].res;//
return 0;
}
void K()//循环语句
{
if(strcmp(new_w.value,"("))
{
error("缺少'('");
}
getWord();//(a>0)中的a
str1=new_w.value;
TJ();//条件
makeFour(op,str1,str2,result);
if(strcmp(new_w.value,")"))
{
error("缺少')'");
}
getWord();
if(strcmp(new_w.value,"do"))
{
error("缺少'do'");
H1();//语句1
}
else
{
getWord();
H1();//语句1
}
}
int H1()//语句1
{
if(strcmp(new_w.value,"{")==0)
{
getWord();
D();//语句部分
return 0;
}
else
{
H();//语句
return 0;
}
}
int TJ()//条件
{
//进Q之前时(a>0)中的a
Q();
if(strcmp(new_w.value,">")==0)
op="<=";
if(strcmp(new_w.value,"<")==0)
op=">=";
if(strcmp(new_w.value,">=")==0)
op="<";
if(strcmp(new_w.value,"<=")==0)
op=">";
if(strcmp(new_w.value,"==")==0)
op="!=";
if(strcmp(new_w.value,"!=")==0)
op="==";
if(new_w.type!=43)
{
error("缺少关系运算符");
}
getWord();
str2=new_w.value;
tj_x=f_num;//记录条件的四元式符号,方便修改他的res
Q();
return 0;
}
int main()
{
char Infile[100];
//对文件的读出和写入借用了网上的知识
printf("要测试的小程序的名字(.txt):");
scanf("%s", Infile);
if ((fin = fopen(Infile, "r")) == NULL)
{
printf("\n 读入文件错误 \n");
return (1);
}
P();
if(e==0)
{
printFour();
}
else
{
cout<<"\n存在语法错误,无法生成四元式"<<endl;
}
return 0;
}