編譯原理:詞法分析程序的設計與實現


詞法分析程序(Lexical Analyzer)要求:


 

  • 從左至右掃描構成源程序的字符流
  • 識別出有詞法意義的單詞(Lexemes
  • 返回單詞記錄(單詞類別,單詞本身)
  • 濾掉空格
  • 跳過注釋
  • 發現詞法錯誤

程序結構:

輸入:字符流(什么輸入方式,什么數據結構保存)

處理

  • 遍歷(什么遍歷方式)
  • 詞法規則

輸出:單詞流(什么輸出形式)

  • 二元組

單詞類別:

  1. 標識符(10)
  2. 無符號數(11)
  3. 保留字(一詞一碼)
  4. 運算符(一詞一碼)
  5. 界符(一詞一碼)

 

單詞符號

種別碼

單詞符號

種別碼

begin

1

:

17

if

2

:=

18

then

3

<

20

while

4

<=

21

do

5

<>

22

end

6

>

23

l(l|d)*

10

>=

24

dd*

11

=

25

+

13

;

26

-

14

(

27

*

15

)

28

/

16

#

0


程序詞法分析代碼:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>//關鍵字 
string key[6]={"main","int","if","else","while","do"}; 
//關鍵字的種別碼
int keyNum[6]={1,2,3,4,5,6}; 
//運算符和界符 
string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};
//char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'};
//運算符和界符的種別碼 
int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
//存放文件取出的字符 
string letter[1000];
//將字符轉換為單詞
string words[1000];
int length; //保存程序中字符的數目 
int num;

//判斷運算符和界符
int isSymbol(string s){  
    int i;
    for(i=0;i<17;i++){
        if(s==symbol[i])
        return symbolNum[i]; 
    }
    return 0;
} 
//判斷是否為數字 
bool isNum(string s){
    if(s>="0" && s<="9")
    return true;
}
//判斷是否為字母 
bool isLetter(string s){
    if(s>="a" && s<="z")
    return true;
}
//判斷是否為關鍵字,是返回種別碼 
int isKeyWord(string s){
    int i;
    for(i=0;i<6;i++){
        if(s==key[i])
        return keyNum[i];
    }
    return 0;
}

//返回單個字符的類型 
int typeword(string str){
    if(str>="a" && str<="z") // 字母 
    return 1;
    
    if(str>="0" && str<="9") //數字 
    return 2;
    
    if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"
    ||str=="+"||str=="-"||str=="*"||str=="/") //判斷運算符和界符 
    return 3; 
}

string identifier(string s,int n){
    int j=n+1;
    int flag=1;
    while(flag){
        if(isNum(letter[j]) || isLetter(letter[j])){
            s=(s+letter[j]).c_str();
            if(isKeyWord(s)){
                j++;
                num=j;
                return s;
            }
        j++;
        }
        else{
            flag=0;
        }
    } 
    num=j;
    return s;
}

string symbolStr(string s,int n){
    int j=n+1;
    string str=letter[j];
    if(str==">"||str=="="||str=="<"||str=="!") {
        s=(s+letter[j]).c_str();
        j++;
    }
    num=j;
    return s;
}

string Number(string s,int n){
    int j=n+1;
    int flag=1;
    while(flag){
        if(isNum(letter[j])){
            s=(s+letter[j]).c_str();
            j++;
        }
        else{
            flag=0;
        }
    }
    num=j;
    return s;
}

void print(string s,int n){
    cout<<"("<<s<<","<<n<<")"<<endl;
}

//取單詞 
void TakeWord(){ 
    int k;
    for(num=0;num<length;){
        string str1,str;
        str=letter[num];
        k=typeword(str);
        switch(k){
            case 1:
                str1=identifier(str,num);
                if(isKeyWord(str1))
                    print(str1,isKeyWord(str1));
                else
                    print(str1,0);
                break;
            case 2:
                str1=Number(str,num);
                print(str1,24);
                break;
            case 3:
                str1=symbolStr(str,num);
                print(str1,isSymbol(str1));
                break; 
        }
    } 
}

int main(){
    char w;
    int i,j;
    freopen("test.txt","r",stdin);//讀取本地文件 
    freopen("result.txt","w",stdout); //從控制台輸出,而不是文本輸出
    length=0;
    while(cin>>w){
        if(w!=' '){
            letter[length]=w;
            length++;
        } //去掉程序中的空格
    }
    TakeWord();
    fclose(stdin);//關閉文件 
    fclose(stdout);//關閉文件 
    return 0;
}

 


運行程序前准備一個分析文本test.txt內容如下:

int main()
{
    int m,n;
    int num=0;
    n=10;
    if(n<0){
       m=-n;
    }
    else{
       m=n;
    }
    while(m!=0){
             num=m*n;
    }
}

執行程序會輸出如下結果:

(int,2)
(main,1)
((,15)
(),16)
({,17)
(int,2)
(m,0)
(,,13)
(n,0)
(;,14)
(int,2)
(num,0)
(=,23)
(0,24)
(;,14)
(n,0)
(=,23)
(10,24)
(;,14)
(if,3)
((,15)
(n,0)
(<,7)
(0,24)
(),16)
({,17)
(m,0)
(=,23)
(-,20)
(n,0)
(;,14)
(},18)
(else,4)
({,17)
(m,0)
(=,23)
(n,0)
(;,14)
(},18)
(while,5)
((,15)
(m,0)
(!=,9)
(0,24)
(),16)
({,17)
(num,0)
(=,23)
(m,0)
(*,21)
(n,0)
(;,14)
(},18)
(},18)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM