📄 实验3.cpp
字号:
//实验三 中间代码生成
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <conio.h>
#include <fstream.h>
#include <iostream.h>
#include <iomanip.h>
/*************************下面是与词法分析相关的一些全局变量与函数的声明*************************/
#define NULL 0
FILE *fp;//源文件的指针
FILE *out,*in;//输出二元式表文件的指针,输出预处理文件的指针
char ch,str;
char filename[50];//源文件路径及名称
char *keyword[4]={"IF","THEN","ELSE","GOTO"};//关键字
char *operatornum[4]={"+","-","*","/"};//运算符
char *comparison[6]={">","<",">=","<=","=","<>"};//关系符
char *interpunction[4]={",",":","(",")"};//界符
bool search(char searchstr[],int wordtype);//查找单词种别函数
char letterprocess(char ch);//字母处理函数
char numberprocess(char ch);//数字处理函数
char otherprocess(char ch);//其它字符处理函数
char process(char ch);//处理空格函数
void pro_process(char *buf);//预处理函数
void Scaner();//词法扫描函数
/*************************下面是与语法分析相关的一些全局变量与函数的声明*************************/
#define N 100
FILE *ff;//读取预处理文件的指针
//定义符号栈的大小与输入字符串的大小以及算术表达式字符串的大小
char stack[N],strings[N],oldstrings[N];
char a;
int top=-1,k=0,step=1,n=0,No[N],id=1;
//二维数组定义字符之间的优先关系(1表示>,-1表示<,0表示=,-2表示错误)
int M[N][N]={{1,1,-1,-1,-1,1,-1,1},{1,1,-1,-1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},{1,1,1,1,-1,1,-1,1},
{-1,-1,-1,-1,-1,0,-1,-2},{1,1,1,1,-2,1,-2,1},{1,1,1,1,-2,1,-2,1},{-1,-1,-1,-1,-1,-2,-1,0}};
char *word[6]={"N+N","N-N","N*N","N/N",")N(","i"};//可归约字符串
void print(int t,int m);//打印算符优先语法分析程序的分析结果
void push(char ch);//入栈函数
char pop();//出栈函数
int ch_di(char ch);//定义字符标识
int IsVT(char ch);//判断是否为终结符
int readvt(char *a);//读入字符
int big(int t,char a);//判断t优先级是否高于a
int less(int t,char a);//判断t优先级是否低于a
int equal(int t,char a);//判断t优先级是否等于a
void error1(int t);//错误分析函数
void prior_analysis();//自下而上分析
void suanfu();//算符优先语法主函数
/*************************下面是与语义分析相关的一些全局变量与函数的声明*************************/
#define MAXLENGTH 63
union WORDCONTENT{//存放单词内容的联合
char T1[MAXLENGTH];
int T2;
char T3;
};
typedef struct WORD{//单词二元组
char syn;
union WORDCONTENT value;
}WORD;
typedef struct QUAD{//四元式的结构
char op[MAXLENGTH];
char argv1[MAXLENGTH];
char argv2[MAXLENGTH];
char result[MAXLENGTH];
}QUATERNION;
QUATERNION *pQuad;//存放四元式的数组
int nSuffix,nNXQ,ntc,nfc,tag1;//临时变量的编号
WORD uWord;//扫描得到的单词
FILE *fw;//输出四元式表文件的指针
void error(char *strError);//输出扫描发现的错误
int Match(char syn,char *strError);//匹配当前识别出的单词
void gen(char *op,char *argv1,char *argv2,char *result);//生成一个四元式
void PrintQuaternion();//打印四元式数组
char *Newtemp();//产生一个临时变量
int merge(int p1,int p2);//合并p1和p2
void backpatch(int p,int t);//将t回填到以p为首的四元式中
char *Expression();//分析算术表达式函数
char *Term();//分析项函数
char *Factor();//分析因子函数
void Condition(int *etc,int *efc);//分析布尔表达式函数
void Statement(int nChain);//语句分析函数
void Statement_Sequence(int nChain);//语句串分析函数
void Parse();//分析生成中间代码
/***********************************以下是词法分析部分***********************************/
//////////////////////////////////////////////////////////////////////////////////////////
bool search(char searchstr[],int wordtype)//查找单词种别函数
{
int i;
switch(wordtype)
{
case 1: for(i=0;i<=3;i++)//识别关键字
{
if(strcmp(keyword[i],searchstr)==0)
return true;
}
case 2: for(i=0;i<=3;i++)//识别运算符
{
if(strcmp(operatornum[i],searchstr)==0)
return true;
}
case 3: for(i=0;i<=5;i++)//识别关系符
{
if(strcmp(comparison[i],searchstr)==0)
return true;
}
case 4: for(i=0;i<=3;i++)//识别界符
{
if(strcmp(interpunction[i],searchstr)==0)
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////////////
char letterprocess(char ch)//字母处理函数
{
int i=-1,j=-1,temp1;
char letter[20],temp[10];
while(isalnum(ch)!=0)
{
letter[++i]=ch;
ch=fgetc(fp);
}
letter[i+1]='\0';
if(search(letter,1))//输出关键字二元式
{
printf("(K,%5s)\n",letter);
fprintf(out,"(K,%s)\n",letter);
if(strcmp(letter,"GOTO")==0)//输出标号二元式
{
ch=fgetc(fp);
while(isdigit(ch)!=0)
{
temp[++j]=ch;
ch=fgetc(fp);
}
temp[j+1]='\0';
printf("(L,%5s)\n",temp);
fprintf(out,"(L,%s)\n",temp);
temp1=atoi(temp);
uWord.syn='L';
uWord.value.T2=temp1;
}
uWord.syn='K';
strcpy(uWord.value.T1,letter);
}
else//输出标识符二元式
{
printf("(I,%5s)\n",letter);
fprintf(out,"(I,%s)\n",letter);
uWord.syn='I';
strcpy(uWord.value.T1,letter);
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char numberprocess(char ch)//数字处理函数
{
int i=-1,temp;
char num[20];
while(isdigit(ch)!=0)
{
num[++i]=ch;
ch=fgetc(fp);
}
if(isalpha(ch)!=0)
{
while(isalpha(ch)!=0)
{
num[++i]=ch;
ch=fgetc(fp);
}
num[i+1]='\0';
printf("非法标识符: %s\n",num);
fprintf(out,"非法标识符: %s\n",num);
}
if(ch==':')//输出标号二元式
{
num[i+1]='\0';
printf("(L,%5s)\n",num);
fprintf(out,"(L,%s)\n",num);
temp=atoi(num);
uWord.syn='L';
uWord.value.T2=temp;
}
else//输出常数二元式
{
num[i+1]='\0';
printf("(C,%5s)\n",num);
fprintf(out,"(C,%s)\n",num);
temp=atoi(num);
uWord.syn='C';
uWord.value.T2=temp;
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char otherprocess(char ch)//其它字符处理函数
{
int i=-1;
char other[10];
if(ch=='(')
{
other[++i]=ch;
ch=fgetc(fp);
}
while(isalnum(ch)==0&&ch!=' '&&ch!='('&&ch!=')')
{
other[++i]=ch;
ch=fgetc(fp);
}
if(ch==')')
{
other[++i]=ch;
ch=fgetc(fp);
}
other[i+1]='\0';
if(search(other,4))//输出界符二元式
{
printf("(P,%5s)\n",other);
fprintf(out,"(P,%s)\n",other);
uWord.syn='P';
uWord.value.T3=other[0];
}
else if(search(other,2)||search(other,3))//输出运算符二元式
{
printf("(O,%5s)\n",other);
fprintf(out,"(O,%s)\n",other);
uWord.syn='O';
strcpy(uWord.value.T1,other);
}
else
{
printf("非法字符: %s\n",other);
fprintf(out,"非法字符: %s\n",other);
}
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char process(char ch)//处理空格函数
{
while(ch==' ')
ch=fgetc(fp);
return ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
void pro_process(char *buf)//预处理函数
{
ifstream cinf(filename,ios::in);
int i=0;//计数器
char old_ch='\0',cur_ch;//前一个字符,当前字符
bool comment=false;//false表示当前字符未处于注释中
while(cinf.read(&cur_ch,sizeof(char)))//从文件读一个字符
{
switch(comment)
{
case false:
if(old_ch=='/'&&cur_ch=='*')//进入注释
{
i--;//去除已存入扫描缓冲区的字符'/'
comment=true;
}
else
{
if(old_ch=='\\'&&cur_ch=='\n')//发现续行
i--;//去除已存入扫描缓冲区的字符'\'
else
{
if(cur_ch=='\t'||cur_ch=='\r'||cur_ch=='\n')//空格取代Tab换行
cur_ch=' ';
if(old_ch==' '&&cur_ch==' ')//一个空格取代多个空格
i--;//去除已存入扫描缓冲区的字符' '
buf[i++]=cur_ch;
}
}
break;
case true:
if(old_ch=='*'&&cur_ch=='/')//离开注释
comment=false;
}
old_ch=cur_ch;//保留前一个字符
}
buf[i++]='#';//在源程序尾部添加字符'#'
}
//////////////////////////////////////////////////////////////////////////////////////////
void Scaner()//词法扫描函数
{
if(str!='#')
{
str=process(str);//空格处理
if(isalpha(str)!=0)
str=letterprocess(str);//字母处理
else
{
if(isdigit(str)!=0)
str=numberprocess(str);//数字处理
else
str=otherprocess(str);//其它字符处理
}
}
else
strcpy(uWord.value.T1,"end");
}
/***********************************以下是语法分析部分***********************************/
//////////////////////////////////////////////////////////////////////////////////////////
void print(int t,int m)//打印算符优先语法分析程序的分析结果
{
cout<<"\n "<<step++<<setw(10);//输出步骤号
cout<<stack<<setw(10);//输出符号栈
if(m==1)//输出优先关系
cout<<">"<<setw(8);
else if(m==0)
cout<<"="<<setw(8);
else
cout<<"<"<<setw(8);
cout<<a<<setw(10);//输出当前分析符
cout<<&strings[k]<<setw(10);//输出剩余输入串
if(t)//输出动作
{
cout<<"归约"<<setw(8);
No[n++]=step-1;
}
else
cout<<"移进"<<setw(8);
}
//////////////////////////////////////////////////////////////////////////////////////////
void push(char ch)//入栈函数
{
stack[++top]=ch;
}
//////////////////////////////////////////////////////////////////////////////////////////
char pop()//出栈函数
{
char a;
a=stack[top--];
stack[top+1]='\0';
return a;
}
//////////////////////////////////////////////////////////////////////////////////////////
int ch_di(char ch)//定义字符标识
{
switch(ch)
{
case'+':
return 1;
case'-':
return 2;
case'*':
return 3;
case'/':
return 4;
case'(':
return 5;
case')':
return 6;
case'i':
return 7;
case'#':
return 8;
default:
return 0;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
int IsVT(char ch)//判断是否为终结符
{
if(ch=='N')
return 0;
else
return 1;
}
//////////////////////////////////////////////////////////////////////////////////////////
int readvt(char *a)//读入字符
{
if(IsVT(strings[k]))
{
(*a)=strings[k];
k++;
return 1;
}
else
{
k++;
return 0;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
int big(int t,char a)//判断t优先级是否高于a
{
if(M[ch_di(stack[t])-1][ch_di(a)-1]==1)
return 1;
else
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////
int less(int t,char a)//判断t优先级是否低于a
{
if(M[ch_di(stack[t])-1][ch_di(a)-1]==-1)
return 1;
else
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////
int equal(int t,char a)//判断t优先级是否等于a
{
if(M[ch_di(stack[t])-1][ch_di(a)-1]==0)
return 1;
else
return 0;
}
//////////////////////////////////////////////////////////////////////////////////////////
void error1(int t)//错误分析函数
{
if(ch_di(stack[t])==6||ch_di(stack[t])==7)
{
printf("\n错误e2:缺少运算符!");
}
else if(ch_di(stack[t])==5)
{
printf("\n错误e1:非法左括号!");
}
else
printf("\n错误e3:非法右括号!");
}
//////////////////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -