?? guyue30.cpp
字號:
#include<stdio.h> //預處理(頭文件包含)
#include<string.h>
#include <conio.h>
#include<iostream.h>
#define MaxiProgramNumber 888 //源程序最大字符的個數
#define MaxiWordLength 18 //標示符和關鍵字最長字符的個數
#define MaxiTokenNumer 118 //標識符能包含的最多的字符個數
/*………………………………………………………………………………………………*/
#define MaxiWordLength1 18
#define MaxiTokenNumer1 118
/*………………………………………………………………………………………………*/
char Ecode[MaxiTokenNumer1][MaxiWordLength1];
int Top=0;
int nID=1; //初始化
/*……………………………下面定義棧結構,棧中的元素是一個結構體………………*/
typedef struct
{
int add;
int next;
char str[MaxiWordLength1];
}ADDL; //ADDL用于識別WHILE,DO
ADDL L[MaxiTokenNumer1]; //L為定義的結構體名
int nL=0;
int nadd=1; //初始化
/*………………………………輸入串棧,棧中元素為結構體……………………………*/
typedef struct
{
int ID;
char b[MaxiWordLength];
}link;
link Token[MaxiTokenNumer];
link Token2[MaxiTokenNumer];
int nTokenNumer=1; //標志位置
char a[MaxiProgramNumber]; //數組用于裝入源程序
int nLength=0; //用于指向數組中的元素
/*……………………………函數聲明(詞法分析部分用到的函數)………………………*/
void GetProgram(); //把源程序裝入數組a
char GetChr(); //將數組a中的元素讀出
int Judge(char& chr); //用于判斷'\0'
int IsLetter(char c); //用于判斷是否為字母
void Input(char* p,char c,int& nx); //標識符或關鍵字進入指針p指向的數組第nx+1個元素
void Save(char* word,int x); //將關鍵字或標志符或算符裝入Token
void Getcode();
/*……………………………函數聲明(語法分析部分用到的函數)………………………*/
void Pop(); //出棧
void InputS();
void InputE1();
void InputE2();
void InputE3();
void InputA();
int firstset();
int panduanSEA(); //識別非終結符
int EStrcmp();
/*…………………………………………詞法分析部分……………………………………*/
int Wordanalyze()
{
int jieshu=0; //詞法分析沒有結束
char chr;
cout<<"*********************請輸入一段源程序(以#為結束標志):************************"<<endl<<endl
<<"************************計算機0305班30號 張古月******************************"<<endl<<endl;
GetProgram(); //把源程序裝入數組a
int x;
char word[MaxiWordLength]; //聲明臨時數組
while((chr=GetChr())!='\0')
{
if(!(Judge(chr)))
{
break;
} //跳過空格和回車取元素
x=0;
word[x]='\0'; //清空
if(IsLetter(chr))
{ jieshu=1;
while(IsLetter(chr))
{
Input(word,chr,x); //是字符就將其裝入數組word
chr=GetChr();
}
if(chr=='>' || chr=='='||chr=='<')
nLength=nLength-1; //指向算符
word[x]='\0';
Save(word,x); //將關鍵字或標志符或算符裝入Token
}
else if(chr=='>') //將'>'裝入Token
{
Input(word,chr,x);
word[x]='\0';
Save(word,x);
}
else if(chr=='=') //將'='裝入Token
{
Input(word,chr,x);
word[x]='\0';
Save(word,x);
}
else if(chr=='<') //將'<'裝入Token
{
Input(word,chr,x);
word[x]='\0';
Save(word,x);
}
else
{
printf("輸入出錯!\n"); //出錯處理
jieshu=0;
return 0;
}
} //這個函數的作用是將輸入符號放入Token
if(jieshu==1) //詞法分析結束
{
Getcode();
printf("單詞符號表為[<種別編碼,單詞屬性>]:\n");
for(int i=1;i<nTokenNumer;i++) //輸出詞法分析結果
{
printf("<");
printf("%d",Token[i].ID);
printf(",");
printf("%s",Token[i].b);
printf(">\n");
strcpy(Token2[i].b,Token[i].b);//將輸入的符號拷貝在Token2中
}
for(int d=1;d<nTokenNumer;d++) //將標識符號替換成id
{
if(Token[d].ID==6)
{
strcpy(Token[d].b,"id");
}
}
strcpy(Token[nTokenNumer].b,"#");
Token[nTokenNumer].ID=7; //'#'的種別編碼為7
return 1;
}
getch();
}
void GetProgram() //把源程序裝入數組a
{
char ch;
while((ch=getchar())!='#')
{
if(nLength>=MaxiProgramNumber-2)
break;
else
a[nLength++]=ch;
}
a[nLength]='\0';
nLength=0;
}
char GetChr() //將數組a中的元素讀出
{
if(nLength>=MaxiProgramNumber-1)
return '\0';
else
return a[nLength++];
}
int Judge(char& chr) //用于判斷'\0',返回值為0時為'\0'
{
while(chr==10 || chr==32) //當chr為空格和換行時
{
chr=GetChr();
if(chr=='\0')
{
return 0;
}
}
return 1;
}
int IsLetter(char c) //用于判斷是否為字母
{
if(c>='a' && c<='z' || c>='A' && c<='Z' )
return 1;
else
return 0;
}
void Input(char* p,char c,int& nx) //標識符或關鍵字進入指針p指向的數組第nx+1個元素
{
if(nx<MaxiWordLength-1)
{
p[nx]=c;
nx++;
}
}
void Save(char* p,int x) //將關鍵字或標志符或算符裝入Token
{
for(int i=0;i<=x;i++)
Token[nTokenNumer].b[i]=p[i];
nTokenNumer=nTokenNumer+1;
}
/*…………………………為不同的輸入符號賦予不同的種別編碼……………………*/
void Getcode()
{
for(int i=1;i<nTokenNumer;i++)
{
if(strcmp(Token[i].b,"while\0")==0)
Token[i].ID=1;
else if(strcmp(Token[i].b,"do\0")==0)
Token[i].ID=2;
else if(strcmp(Token[i].b,">\0")==0)
Token[i].ID=3;
else if(strcmp(Token[i].b,"=\0")==0)
Token[i].ID=4;
else if(strcmp(Token[i].b,"<\0")==0)
Token[i].ID=5;
else
Token[i].ID=6;
}
}
/*………………………………………語法分析過程……………………………………*/
int ExpressionAnalyse() //語法分析
{
printf("\n語法分析得出:\n");
strcpy(Ecode[Top++],"#"); //將#壓棧
strcpy(Ecode[Top++],"S"); //將S壓棧
int FLAG=1; //語法分析未結束標志
while(FLAG)
{
int f1=0;
f1=panduanSEA();
if(f1==1)
{
cout<<" S->while E do A"<<endl;
InputS();
}
else if(f1==2)
{ int f3=0;
f3=firstset();
if(f3==1)
{
cout<<" E->id>id"<<endl;
InputE1();
}
else if(f3==2)
{
cout<<" E->id=id\n"<<endl;
InputE2();
}
else
{
cout<<" E->id<id"<<endl;
InputE3();
}
}
else if(f1==3)
{
cout<<" A->id=id"<<endl;
InputA();
}
else
{
int f2=0;
f2=EStrcmp();
if(f2==1) //識別出關鍵字
{
Pop();
nID=nID+1;
}
else if(f2==3) //識別出#,分析結束
{
cout<<endl<<"語法正確!"<<endl;
FLAG=0;
return 1;
}
else
{
cout<<endl<<"語法出錯啦!"<<endl;
FLAG=0;
return 0;
}
}
}
getch();
}
void InputS() //壓棧
{
Pop();
strcpy(Ecode[Top++],"A");
strcpy(Ecode[Top++],"do");
strcpy(Ecode[Top++],"E");
strcpy(Ecode[Top++],"while");
}
void InputE1() //壓棧
{
Pop();
strcpy(Ecode[Top++],"id");
strcpy(Ecode[Top++],">");
strcpy(Ecode[Top++],"id");
}
void InputE2() //壓棧
{
Pop();
strcpy(Ecode[Top++],"id");
strcpy(Ecode[Top++],"=");
strcpy(Ecode[Top++],"id");
}
void InputE3() //壓棧
{
Pop();
strcpy(Ecode[Top++],"id");
strcpy(Ecode[Top++],"<");
strcpy(Ecode[Top++],"id");
}
void InputA() //壓棧
{
Pop();
strcpy(Ecode[Top++],"id");
strcpy(Ecode[Top++],"=");
strcpy(Ecode[Top++],"id");
}
void Pop() //出棧操作
{
Top=Top-1;
}
int firstset()
{
if(strcmp(Token2[3].b,">")==0)
return 1;
if(strcmp(Token2[3].b,"=")==0)
return 2;
if(strcmp(Token2[3].b,"<")==0)
return 3;
}
int panduanSEA() //識別非終結符
{
if(strcmp(Ecode[Top-1],"S")==0)
return 1;
else if(strcmp(Ecode[Top-1],"E")==0)
return 2;
else if(strcmp(Ecode[Top-1],"A")==0)
return 3;
else
return 4;
}
int EStrcmp() //識別while和do關鍵字
{
if(strcmp(Ecode[Top-1],"#")==0)
{
if(strcmp(Token[nID].b,"#")==0)
return 3;
}
else if(strcmp(Ecode[Top-1],Token[nID].b)==0)
{
if(strcmp(Ecode[Top-1],"while")==0)
{
L[nL].add=nadd++;
L[nL].next=nadd++;
strcpy(L[nL].str ,"while");
nL++;
}
if(strcmp(Ecode[Top-1],"do")==0)
{
L[nL].add=nadd++;
L[nL].next=L[nL-1].add;
strcpy(L[nL].str ,"do");
nL++;
}
return 1;
}
else
return 0;
cout<<Token[2].b<<endl;
}
/*……………………………………語義分析……………………………………*/
void main()
{
cout<<"****************************編譯原理課程設計:*********************************"<<endl<<endl;
cout<<"*************while語句的翻譯分析程序,采用LL(1)法,輸出三地址:*************"<<endl<<endl;
cout<<"***************************程序所用的文法為:*********************************"<<endl;
cout<<" S->while E do A"<<endl;
cout<<" E->id>id|E->id=id|E->id<id"<<endl;
cout<<" A->id=id"<<endl;
cout<<" (id代表標識符)"<<endl;
if(Wordanalyze()) //詞法分析成功
{
if(ExpressionAnalyse()) //語法分析也成功
{
int i;
L[nL].add=nadd;
for(i=0;i<nL;i++)
{
if(strcmp(L[i].str,"while")==0)
{ cout<<endl;
cout<<"正確的語義輸出為:"<<endl;
cout<<"L0: if "<<Token2[2].b<<" > "<<Token2[4].b<<" goto L2"<<endl;
cout<<"L1: if not goto L4"<<endl;
}
else
{
cout<<"L2: "<<Token2[6].b<<":="<<Token2[8].b<<endl;
cout<<"L3: "<<"goto L0"<<endl;
cout<<"L4: "<<endl;
}
}
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -