?? 實驗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 + -