深入浅出编译原理-4-一个简单词法分析器的C语言实现

来源:岁月联盟 编辑:猪蛋儿 时间:2012-07-10

引言

光说不练,假把式。

此小节来做一个实验,用c语言自己实现一个简单的词法分析器,来加深对词法分析的理解。感兴趣的就自己分析一下源码吧,挺简单的,就没画流程图,请见谅。闲言少叙,我们开始吧。

 

4.1实验描述

例如:对源程序:

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


的源文件,经过词法分析后输出如下序列:

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

 

4.1.1待分析的简单的词法

(1)关键字:

 begin  if  then  while  do  end

所有的关键字都是小写。

(2)运算符和界符

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

(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:

ID = letter (letter | digit)*

NUM = digit digit*

(4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。

4.1.2 各种单词符号对应的种别码:

表4.2.1 各种单词符号对应的种别码

单词符号

种别码

单词符号

种别码

bgin

1

17

If

2

:=

18

Then

3

<

20

wile

4

<>

21

do

5

<=

22

end

6

>

23

lettet(letter|digit)*

10

>=

24

dight dight*

11

=

25

+

13

26

14

(

27

*

15

)

28

/

16

#

0

 

 

4.2实现源码参考

 

[html] 
#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'; 

 

 

4.3小结:

词法分析,就是将程序源代码序列,循环读取一个字串,然后根据词法要求,确定其属性,然后组成词法单元。对于现实中的编程语言,其词法比较复杂,一般用正则表达式表示。


作者:rill_zhen

图片内容