?? 語法分析程序.txt
字號:
/*************************************************************************
* 語法分析1:遞歸子程序法
*
* 問題描述:設定好自己的文法
* 從控制臺讀取文件,運用以上文法進行語法分析。
* 將分析結果顯示在屏幕上并存入另一文件中。
*
* 說明:1、采用功能獨立的小函數段實現。
* 2、使用遞歸子程序法。
* 3、內碼對照表見《編譯方法》(馬知行,曹啟君編)P167。
* 4、本程序實現過程未參照上述書上。
* 5、本程序在原有詞法分析程序基礎上修改而成。
* 6、所讀取文件和存儲文件在本工程所在目錄下。
* 7、定義文法:(讀取文件以"#"結尾)
* (1)主函數:S()
* void main()
* {
* 整型定義;
* 整型定義;
* for循環;
* if判斷;
* return;
* }
* (2)整型定義或賦值(a為任一標示符):A()
* int a=2;
* 或:
* a=3;
* (3)for循環:B()
* for(i=0;i<3;i++)(i為任一標示符)
* {
* 整型賦值;
* }
* (4)if判斷:C()
* if(a=0)
* {
* 整型賦值;
* }
*
************************************************************************/
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<process.h>
#include<iostream.h>
#define LENKEY 15
#define LENSIGN 17
#define WRITEFILE "D:\\write.txt"
struct{
char name[31];
int addr;
}word[1000]; //word[1000]: 存儲已分析單詞的名稱和內碼
char *keyword[LENKEY] = {"program","const","var","integer","long","procedure","if","then","while","do","read","write","begin","end","odd"};
char *sign[LENSIGN] = {"+","-","*","/","=","<>","<","<=",">",">=",".",",",";",":",":=","(",")"};
FILE *f,*fw;
int totalwords = 0; //totalwords: 當前已分析單詞的數量
int next=0; //next: 當前的單詞序號
char w[20];
void SaveWords(int,char *[]); //SaveWords(): 將文件中的單詞存入word[]中
void get_w(); //get_w(): 讀取一個單詞
void S(); //S(): 分析main()函數
void A(); //A(): 分析整型定義和賦值
void B(); //B(): 分析for循環
void C(); //C(): 分析if判斷
void OpenFile(char *,char *); //OpenFile(): 打開文件
void ReadLine(FILE *,char []); //ReadLine(): 讀取文件中一行
void DealLine(char []); //DealLine(): 處理一行
bool Analyse(char []); //Analyse(): 分析一個單詞
bool AnalyseSign(char []); //AnalyseSign(): 分析一個符號單詞
bool AnalyseAlpha(char a[]); //AnalyseAlpha(): 分析一個關鍵字或標示符單詞
bool AnalyseNum(char n[]); //AnalyseNum(): 分析一個整數單詞
void DealError(char []); //DealError(): 處理錯誤信息
void DealResult(FILE *); //DealResult(): 輸出結果,并將結果寫入文件
/*************************************************************************
* 主函數
************************************************************************/
void main(int argc,char *argv[])
{
SaveWords(argc,argv);
//語法分析
get_w();
S();
get_w();
if(strcmp(w,"#")!=0)
{
cout<<""<<endl;
fprintf(fw,"Error!");
}
return;
fclose(fw);
}
/*************************************************************************
* 函數名稱:
* get_w()
* 參數:
* 無。
* 返回值:
* 空。
* 功能:
* 從word[]中讀取一個單詞。
************************************************************************/
void get_w()
{
strcpy(w,word[next].name);
next++;
}
/*************************************************************************
* 函數名稱:
* S()
* 參數:
* 無。
* 返回值:
* 空。
* 功能:
* 分析主函數。
************************************************************************/
void S()
{
if(strcmp(w,"void")==0)
{
get_w();
if(strcmp(w,"main")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A(); //定義整型變量
get_w();
A(); //定義整型變量
get_w();
B(); //判斷for循環
get_w();
C(); //判斷if判斷
get_w();
if(strcmp(w,"return")==0)
{
get_w();
if(strcmp(w,";")==0)
{
get_w();
if(strcmp(w,"}")==0)
{
cout<<"符合所定義語法"<<endl;
fprintf(fw,"符合所定義語法");
return;
}
}
}
}
}
}
}
}
cout<<"不符合所定義語法"<<endl;
fprintf(fw,"不符合所定義語法");
return;
}
/*************************************************************************
* 函數名稱:
* A()
* 參數:
* 無。
* 返回值:
* 空。
* 功能:
* 分析整型定義或賦值。
************************************************************************/
void A()
{
if(strcmp(w,"int")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
return;
}
}
}
}
else if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
return;
}
}
}
cout<<"A不符合整型定義"<<endl;
fprintf(fw,"A不符合整型定義");
return;
}
/*************************************************************************
* 函數名稱:
* B()
* 參數:
* 無。
* 返回值:
* 空。
* 功能:
* 分析for循環。
************************************************************************/
void B()
{
if(strcmp(w,"for")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
A(); //i=0
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"<")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,";")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"+")==0)
{
get_w();
if(strcmp(w,"+")==0)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A();
get_w();
if(strcmp(w,"}")==0)
{
return;
}
}
}
}
}
}
}
}
}
}
}
}
cout<<"B不符合for循環定義"<<endl;
fprintf(fw,"B不符合for循環定義");
}
/*************************************************************************
* 函數名稱:
* C()
* 參數:
* 無。
* 返回值:
* 空。
* 功能:
* 判斷if語句。
************************************************************************/
void C()//if判斷
{
if(strcmp(w,"if")==0)
{
get_w();
if(strcmp(w,"(")==0)
{
get_w();
if(word[next-1].addr==34)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(strcmp(w,"=")==0)
{
get_w();
if(word[next-1].addr==33)
{
get_w();
if(strcmp(w,")")==0)
{
get_w();
if(strcmp(w,"{")==0)
{
get_w();
A();
get_w();
if(strcmp(w,"}")==0)
{
return;
}
}
}
}
}
}
}
}
}
cout<<"C不符合if循環定義"<<endl;
fprintf(fw,"C不符合if循環定義");
}
/*************************************************************************
* 函數名稱:
* SaveWords()
* 參數:
* int argc2 - 控制臺輸入的參數個數;
* char *argv2[] - 控制臺輸入的參數。
* 返回值:
* 空。
* 功能:
* 將文件中讀取的單詞存入word[]中。
************************************************************************/
void SaveWords(int argc2,char *argv2[])
{
FILE *fread,*fwrite;
char line[200];
//打開文件
OpenFile(argv2[2],"w");
fw=f;
OpenFile(argv2[1],"r");
fread=f;
if(argc2<3)OpenFile(WRITEFILE,"w");
else OpenFile(argv2[2],"w");
fwrite=f;
//讀取一行,處理一行
while(!feof(fread))
{
ReadLine(fread,line);
DealLine(line);
}
//關閉文件
fclose(fread);
fclose(fwrite);
}
/*************************************************************************
* 函數名稱:
* OpenFile()
* 參數:
* char *route - 文件所在路徑;
* char *manner - 文件打開方式。
* 返回值:
* 空。
* 功能:
* 打開文件。
************************************************************************/
void OpenFile(char *route,char *manner)
{
if((f = fopen(route,manner))==NULL)
{
printf("connot open the file\n");
exit(0);
}
}
/*************************************************************************
* 函數名稱:
* ReadLine()
* 參數:
* FILE *f - 所要讀取的文件;
* char line[] - 讀到的一行。
* 返回值:
* 空。
* 功能:
* 讀取文件中的一行。
************************************************************************/
void ReadLine(FILE *f,char line[])
{
if(feof(f))return;
int i=0;
char ch = fgetc(f);
while(ch!='\n'&&!feof(f))
{
line[i]=ch;
i++;
ch = fgetc(f);
}
line[i] = '\0';
return;
}
/*************************************************************************
* 函數名稱:
* DealLine()
* 參數:
* char line[] - 已讀取的文件中的一行。
* 返回值:
* 空。
* 功能:
* 處理已讀取的文件中的一行。
************************************************************************/
void DealLine(char line[])
{
int i=0,n=0;
char str[30];
while(line[i]!='\0')
{
//略去空格
while(isspace(line[i]))
i++;
//關鍵字、標示符、無符號整數(字母、數字、下劃線的組合)
while((line[i]!='\0')&&(isalnum(line[i])||isalpha(line[i])||line[i]=='_'))
{
str[n]=line[i];
n++;
i++;
}
if(n>0)
{
str[n]='\0';
if(!Analyse(str))
{
i=i-strlen(str);
str[0]=line[i];
str[1]='\0';
i++;
Analyse(str);
}
n=0;
}
//符號、錯誤詞法
while((line[i]!='\0')&&(!isalnum(line[i]))&&(!isalpha(line[i]))&&(line[i]!='_'))
{
while(isspace(line[i]))
i++;
if((line[i]!='\0')&&((isalnum(line[i]))||(isalpha(line[i]))||(line[i]=='_')))break;
str[n]=line[i];
n++;
i++;
}
if(n>0)
{
str[n]='\0';
if(!Analyse(str))
{
i=i-strlen(str);
str[0]=line[i];
str[1]='\0';
i++;
Analyse(str);
}
n=0;
}
}
return;
}
/*************************************************************************
* 函數名稱:
* Analyse()
* 參數:
* char str[] - 在一行中提取的一個單詞。
* 返回值:
* true - 處理無異常。
* false - 該單詞包含相鄰的字符,需退出重新劃分單詞。
* 功能:
* 分析一個單詞。
************************************************************************/
bool Analyse(char str[])
{
int n=0,i=0,num=0;
//以字母或下劃線開頭
if((isalpha(str[0]))||(str[0]=='_'))
AnalyseAlpha(str);
//以數字開頭
else if(isalnum(str[0]))
{
if(!AnalyseNum(str))
DealError(str);
}
//其它情況
else
{
//多個符號相鄰的情況
if((strlen(str)>1)&&(strcmp(str,"<>")!=0)&&(strcmp(str,"<=")!=0)&&(strcmp(str,">=")!=0)&&(strcmp(str,":=")!=0))
return false;
if(!AnalyseSign(str))
DealError(str);
}
return true;
}
/*************************************************************************
* 函數名稱:
* AnalyseAlpha()
* 參數:
* char a[] - 待分析的字母和數字組合單詞。
* 返回值:
* true - 屬于內部碼中的單詞。
* 功能:
* 分析一個單詞是否是關鍵字或標示符。
************************************************************************/
bool AnalyseAlpha(char a[])
{
int i=0;
for(i=0;i<LENKEY;i++)
{
if(!strcmp(a,keyword[i]))
{
strcpy(word[totalwords].name,keyword[i]);
word[totalwords].addr = i+1;
totalwords++;
return true;
}
}
strcpy(word[totalwords].name,a);
word[totalwords].addr = 34;
totalwords++;
return true;
}
/*************************************************************************
* 函數名稱:
* AnalyseNum()
* 參數:
* char n[] - 待分析的符號單詞。
* 返回值:
* true - 屬于內部碼中的單詞。
* false - 不屬于內部碼中的無符號整數。
* 功能:
* 分析一個單詞是否是內部碼中的無符號整數。
************************************************************************/
bool AnalyseNum(char n[])
{
int i=0;
for(i=0;i<(int)strlen(n);i++)
if(n[i]<'0'||n[i]>'9')
return false;
strcpy(word[totalwords].name,n);
word[totalwords].addr = 33;
totalwords++;
return true;
}
/*************************************************************************
* 函數名稱:
* AnalyseSign()
* 參數:
* char s[] - 待分析的符號單詞。
* 返回值:
* true - 屬于內部碼中的單詞。
* false - 不屬于內部碼中的符號單詞。
* 功能:
* 分析一個單詞是否是內部碼中的符號單詞。
************************************************************************/
bool AnalyseSign(char s[])
{
int i=0;
for(i=0;i<LENSIGN;i++)
{
if(!strcmp(s,sign[i]))
{
strcpy(word[totalwords].name,s);
word[totalwords].addr = i+16;
totalwords++;
return true;
}
}
if(!strcmp(s,"#"))
{
strcpy(word[totalwords].name,s);
word[totalwords].addr = 35;
totalwords++;
return true;
}
return false;
}
/*************************************************************************
* 函數名稱:
* DealError()
* 參數:
* char str[] - 錯誤的單詞。
* 返回值:
* 空。
* 功能:
* 處理錯誤單詞。
************************************************************************/
void DealError(char str[])
{
strcpy(word[totalwords].name,str);
word[totalwords].addr = 36;
totalwords++;
return;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -