1. 程式人生 > >一個簡單詞法分析器的C語言實現

一個簡單詞法分析器的C語言實現

1.1實驗描述

例如:對源程式:

begin x:=9: if x>9 then x:=2*x+1/3; end #

的原始檔,經過詞法分析後輸出如下序列:

<1,begin><10,x><18,:=><11,9><26,;><2,if>……

1.1.1待分析的簡單的詞法

1)關鍵字:

 begin  if  then  while  do  end

所有的關鍵字都是小寫。

2)運算子和界符

 =  +  -  *  /  <  <=  <>  >  >=  =  ; (  )  #

3)其他單詞是識別符號(ID)和整型常數(SUM),通過以下正規式定義:

ID = letter (letter | digit)*

NUM = digit digit*

4)空格有空白、製表符和換行符組成。空格一般用來分隔IDSUM、運算子、界符和關鍵字,詞法分析階段通常被忽略。

1.1.2 各種單詞符號對應的種別碼:

表4.2.1 各種單詞符號對應的種別碼

單詞符號

種別碼

單詞符號

種別碼

bgin

1

17

If

2

=

18

Then

3

20

wile

4

<> 

21

do

5

<=

22

end

6

23

lettetletter|digit*

10

>=

24

dight dight*

11

=

25

+

13

26

14

(

27

*

15

)

28

/

16

#

0


2.2實現原始碼參考
#include <stdio.h>  
#include <string.h>  
  
char prog[80],token[8],ch;  
int syn,p,m,n,sum;  
char *rwtab[6]={"begin","if","then","while","do","end"};  
   
void scaner(void);  
  
main()  
{  
    p=0;  
    printf("\n please input a string(end with '#'):\n");  
      
    do{  
            scanf("%c",&ch);  
            prog[p++]=ch;  
    }while(ch!='#');  
      
    p=0;  
    do{  
            scaner();  
            switch(syn)  
            {  
                case 11:  
                    printf("( %-10d%5d )\n",sum,syn);  
                break;  
                  
                case -1:  
                    printf("you have input a wrong string\n");  
                    //getch();  
                    return 0;  
                break;  
                  
                default:   
                printf("( %-10s%5d )\n",token,syn);  
                break;  
            }  
        }while(syn!=0);  
    //getch();  
 }  
  
void scaner(void)  
{    
    sum=0;  
      
    for(m=0;m<8;m++)  
        token[m++]= NULL;  
      
        ch=prog[p++];  
        m=0;  
          
    while((ch==' ')||(ch=='\n'))  
        ch=prog[p++];  
      
    if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))  
     {   
        while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))  
        {  
            token[m++]=ch;  
            ch=prog[p++];  
        }  
          
        p--;  
        syn=10;  
  
        for(n=0;n<6;n++)  
        if(strcmp(token,rwtab[n])==0)  
        {   
            syn=n+1;  
            break;  
        }  
     }  
     else if((ch>='0')&&(ch<='9'))  
     {   
        while((ch>='0')&&(ch<='9'))  
        {  
            sum=sum*10+ch-'0';  
            ch=prog[p++];  
        }  
        p--;  
        syn=11;  
    }  
    else   
    {  
        switch(ch)  
        {  
        case '<':  
            token[m++]=ch;  
            ch=prog[p++];  
            if(ch=='=')  
            {   
                syn=22;  
                token[m++]=ch;  
            }  
            else  
            {    
                syn=20;  
                p--;  
            }  
        break;  
  
        case '>':  
            token[m++]=ch;  
            ch=prog[p++];  
            if(ch=='=')  
            {  
                syn=24;  
                token[m++]=ch;  
            }  
            else  
            {   
                syn=23;  
                p--;  
            }  
        break;  
  
        case '+':  
            token[m++]=ch;  
            ch=prog[p++];  
            if(ch=='+')  
            {  
                syn=17;  
                token[m++]=ch;  
            }  
            else  
            {  
                syn=13;  
                p--;  
            }  
        break;  
  
        case '-':  
            token[m++]=ch;  
            ch=prog[p++];  
            if(ch=='-')  
            {  
                syn=29;  
                token[m++]=ch;  
            }  
            else  
            {   
                syn=14;  
                p--;  
            }  
        break;  
  
        case '!':  
            ch=prog[p++];  
            if(ch=='=')  
            {   
                syn=21;  
                token[m++]=ch;  
            }  
            else  
            {   
                syn=31;  
                p--;  
            }  
        break;  
  
        case '=':  
            token[m++]=ch;  
            ch=prog[p++];  
            if(ch=='=')  
            {  
                syn=25;  
                token[m++]=ch;  
            }  
            else  
            {  
                syn=18;  
                p--;  
            }  
        break;  
  
        case '*':  
            syn=15;  
            token[m++]=ch;  
        break;  
  
        case '/':  
            syn=16;  
            token[m++]=ch;  
        break;  
  
        case '(':   
            syn=27;  
            token[m++]=ch;  
        break;  
  
        case ')':  
            syn=28;  
            token[m++]=ch;  
        break;  
  
        case '{':   
            syn=5;  
            token[m++]=ch;  
        break;  
  
        case '}':   
            syn=6;  
            token[m++]=ch;  
        break;  
  
        case ';':  
            syn=26;  
            token[m++]=ch;  
        break;  
  
        case '\"':  
            syn=30;  
            token[m++]=ch;  
        break;  
  
        case '#':   
            syn=0;  
            token[m++]=ch;  
        break;  
  
        case ':':  
            syn=17;  
            token[m++]=ch;  
        break;  
  
        default:  
            syn=-1;  
        break;  
        }  
    }  
        token[m++]='\0';  
}  

1.3小結:

詞法分析,就是將程式原始碼序列,迴圈讀取一個字串,然後根據詞法要求,確定其屬性,然後組成詞法單元。對於現實中的程式語言,其詞法比較複雜,一般用正則表示式表示。