數據結構之簡易詞法分析(未包含錯誤分析)

#include
#include <stdio.h>
#include <string>
#include <ctype.h>


const int WORD_SIZE=100; //用來存儲臨時變量的大小
int Line=1; //全局變量用以輸出單詞所在行數


using namespace std;


string Key1[20]={"asm","auto","break","case","cdecl","char","const","continue","default", //定義關鍵字表1
"do","double","else","enum","extern","far","float","for","goto","huge","if"};


string Key2[20]={"interrupt","int","long","near","pascal","register","return","short","signed", //定義關鍵字表2
"sizeof","static","struct","switch","typedef","union","unsigned","void",
"volatile","while","main"}; //其中main不爲關鍵字,只爲添加便於循環


char Alphaprocess(FILE* &fp,char ch){ //字母過程,用來判斷標識符與關鍵字
char tempBuffer[WORD_SIZE]; //字符數組臨時變量,用以存放該函數用以處理的字符串(字符數組)


int i=0;


while(ch=='_' || isalnum(ch) ){ //將其後多個字符存入字符數組中 isalnum()爲庫函數,以下判斷字符或數字等的函數均來自ctype頭文件
tempBuffer[i]=ch;
ch=getc(fp);
i++;
}

fseek(fp,-1,1); //多處理了一個字符,故將文件指針後移一個單位


tempBuffer[i]=NULL; //將數組中最後一個字符設爲空,否則輸出該字符數組時會有一系列亂碼。比如:燙燙燙燙(編譯環境爲vc++6.0)


for(i=0;i<20;i++){ //將獲得的字符數組與關鍵字表進行比較,輸出編號爲0
if(Key1[i]==tempBuffer || Key2[i]==tempBuffer){
cout<<"Line:"<<Line<<" "<<"(0,"<<tempBuffer<<")"<<endl;
return ch;
}
}


cout<<"Line:"<<Line<<" "<<"(1,"<<tempBuffer<<")"<<endl; //未找到關鍵字,則爲標識符,輸出編號爲1
return ch;
}


char Digitprocess(FILE* &fp,char ch){ //數字過程,用以判斷數字常量
char tempBuffer[WORD_SIZE];
int i=0;


while(isdigit(ch) || ch=='.'){
tempBuffer[i]=ch;
ch=getc(fp);
i++;
}

fseek(fp,-1,1);                           //對多處理的一個字符進行還原


tempBuffer[i]=NULL;

cout<<"Line:"<<Line<<" "<<"(2,"<<tempBuffer<<")"<<endl; //數字編號爲3
return ch;
}


char Otherprocess(FILE* &fp,char ch){ //特殊符號過程
int id=3;
char tempBuffer[3];


tempBuffer[0]=ch;
tempBuffer[1]=NULL;


if(ch=='(' || ch==')' || ch=='{' || ch=='}' || ch=='[' || ch==']'
|| ch==',' || ch==';'){
id=4;
}




if(ch=='-'){ //對特殊符號進行補充
ch=getc(fp);
if(ch=='=' || ch=='-') //判斷-=  與 --
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}


if(ch=='+'){
ch=getc(fp);
if(ch=='=' || ch=='+')
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}


if(ch=='>'){
ch=getc(fp);
if(ch=='=')
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}


if(ch=='<'){
ch=getc(fp);
if(ch=='=')
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}

if(ch=='!'){
ch=getc(fp);
if(ch=='=')
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}


if(ch=='='){
ch=getc(fp);
if(ch=='=')
tempBuffer[1]=ch;
else{
fseek(fp,-1,1);
}
}




tempBuffer[2]=NULL;


cout<<"Line:"<<Line<<" "<<"("<<id<<","<<tempBuffer<<")"<<endl;
return ch;
}


void main()
{
char ch;
FILE *fp;
char file[100];
cout<<"輸入你要進行詞法分析的文件:";
cin>>file;


cout<<"---------------------------------------------------"<<endl;
cout<<"---------------------------------------------------"<<endl;
cout<<endl;
cout<<endl;


if((fp=fopen(file,"r"))==NULL){ //打開文件
cout<<"File opened Error!"<<endl;
return;
}


do{ //將文件內容輸出到命令行窗口
ch=getc(fp);
cout<<ch;
}while(ch!=EOF);

fseek(fp,0,0); //將文件指針移動至文件開始處


cout<<endl;
cout<<endl;

do{
ch=getc(fp); //第二次對文件進行遍歷,將取得的各個字符用相對應的過程函數解決
if(ch==' ' || ch=='\n'){
if(ch=='\n')
Line++; //遇到換行符,行號加1
}
// ch=getc(fp);
else if(isalpha(ch) || ch=='_')
ch=Alphaprocess(fp,ch); //以各個對應的函數解決
else if(isdigit(ch))
ch=Digitprocess(fp,ch);
else if(ispunct(ch))
ch=Otherprocess(fp,ch);
}while(ch!=EOF);


fclose(fp); //關閉文件*/

}


//課程較緊,老師也未深入講解,故只做了簡單地分析,也有很多未考慮的地方,不足之處也顯而易見,對於註釋的解決,浮點數的判斷正誤,函數名的判別等等




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章