编译原理之词法分析器(二)

上一篇我们用二维数组实现了状态机,但是我们可以看到,使用二维数组实现浪费了很多内存,实际上我们可以使用其他的方式来实现状态机,也就是说状态机并不是只有一种实现方式,很多数据结构有很多种实现方式,但对于同一种数据结构基本的思想是相同的。其实学习词法分析实际最重要的是学习状态机的实现过程,代码都是次要的,每种实现过程都有优点和缺点。

本文内容:

1:状态机的另一种实现方式(Switch语句实现)

2:评价该实现的方式优缺点

下面我们使用switch的case结构来实现这一过程:

状态机的状态转移图如下所示:

我们使用的是switch语句实现:

代码如下:

头文件:

/***
* 编写人:
* 时  间:2019.11.25
* 文件名:lexer.h
* 说  明:词法分析器
***/

/**
下面是所有能识别的关键字
 关键字           ID
 uint8             1
 uint16            2
 uint32            3
 int8              4
 int16             5
 int32             6

 if                20
 for               21
 while             22
 switch            23
 case              24
 goto              25
**/

/**********************
下面定义状态表
***********************/

#ifndef __MYLAXER_
#define __MYLAXER_

typedef struct Lexer
{
    int  id;
    char Label[20];
}LexerPro;

LexerPro Analyser(char *sream);

#endif

源文件:

/***
* 编写人:
* 时  间:2019.11.25
* 文件名:lexer.c
* 说  明:词法分析器
***/
#include "lexer.h"
#include "stdio.h"

LexerPro Analyser(char *sream)
{
    int state=0;  //初始化状态为0
    LexerPro Resl={0,""};
    int i=0;
    while(*sream)
    {
        Resl.Label[i++]=*sream;
        switch(state)
        {
            case 0:
                if(*sream==' ')
                   {state=0;break;}
                else if(*sream=='u')
                   {state=0;break;}
                else if(*sream=='i')
                   {state=10;break;}
                else if(*sream=='f')
                   {state=19;break;}
                else if(*sream=='w')
                   {state=22;break;}
                else if(*sream=='s')
                   {state=27;break;}
                else if(*sream=='c')
                   {state=27;break;}
                else if(*sream=='g')
                   {state=37;break;}
                else
                   {state=255;break;}
            case 1:
                if(*sream=='i')
                   {state=2;break;}
                else
                    {state=255;break;}
            case 2:
                if(*sream=='n')
                   {state=3;break;}
                else
                    {state=255;break;}
            case 3:
                if(*sream=='t')
                   {state=4;break;}
                else
                    {state=255;break;}
            case 4:
                if(*sream=='8')
                   {state=5;break;}
                else if(*sream=='1')
                   {state=6;break;}
                else if(*sream=='3')
                   {state=8;break;}
                else
                   {state=255;break;}
            case 5:
                if(*sream==' ')
                   {Resl.id=1;return Resl;}
                else
                   {state=255;break;}
            case 6:
                if(*sream=='6')
                   {state=7;break;}
                else
                    {state=255;break;}
            case 7:
                if(*sream==' ')
                   {Resl.id=2;return Resl;}
                else
                    {state=255;break;}
            case 8:
                if(*sream=='2')
                   {state=9;break;}
                else
                    {state=255;break;}
            case 9:
                if(*sream==' ')
                   {Resl.id=3;return Resl;}
                else
                    {state=255;break;}
            case 10:
                if(*sream=='f')
                   {state=18;break;}
                else if(*sream=='n')
                   {state=11;break;}
                else
                    {state=255;break;}
            case 11:
                if(*sream=='t')
                   {state=12;break;}
                else
                    {state=255;break;}
            case 12:
                if(*sream=='8')
                   {state=13;break;}
                else if(*sream=='1')
                   {state=14;break;}
                else if(*sream=='3')
                   {state=16;break;}
                else
                    {state=255;break;}
            case 13:
                if(*sream==' ')
                   {Resl.id=4;return Resl;}
                else
                    {state=255;break;}
            case 14:
                if(*sream=='6')
                   {state=15;break;}
                else
                    {state=255;break;}
            case 15:
                if(*sream==' ')
                   {Resl.id=5;return Resl;}
                else
                    {state=255;break;}
            case 16:
                if(*sream=='2')
                   {state=17;break;}
                else
                    {state=255;break;}
            case 17:
                if(*sream==' ')
                   {Resl.id=6;return Resl;}
                else
                    {state=255;break;}
            case 18:
                if(*sream==' ')
                   {Resl.id=20;return Resl;}
                else
                    {state=255;break;}
            case 19:
                if(*sream=='o')
                   {state=20;break;}
                else
                    {state=255;break;}
            case 20:
                if(*sream=='r')
                   {state=21;break;}
                else
                    {state=255;break;}
            case 21:
                if(*sream==' ')
                   {Resl.id=21;return Resl;}
                else
                    {state=255;break;}
            case 22:
                if(*sream=='h')
                   {state=23;break;}
                else
                    {state=255;break;}
            case 23:
                if(*sream=='i')
                   {state=24;break;}
                else
                    {state=255;break;}
            case 24:
                if(*sream=='l')
                   {state=25;break;}
                else
                    {state=255;break;}
            case 25:
                if(*sream=='e')
                   {state=26;break;}
                else
                    {state=255;break;}
            case 26:
                if(*sream==' ')
                   {Resl.id=22;return Resl;}
                else
                    {state=255;break;}
            case 27:
                if(*sream=='w')
                   {state=28;break;}
                else
                    {state=255;break;}
            case 28:
                if(*sream=='i')
                   {state=29;break;}
                else
                    {state=255;break;}
            case 29:
                if(*sream=='t')
                   {state=30;break;}
                else
                    {state=255;break;}
            case 30:
                if(*sream=='c')
                   {state=31;break;}
                else
                    {state=255;break;}
            case 31:
                if(*sream=='h')
                   {state=32;break;}
                else
                    {state=255;break;}
            case 32:
                if(*sream==' ')
                   {Resl.id=23;return Resl;}
                else
                    {state=255;break;}
            case 33:
                if(*sream=='a')
                   {state=34;break;}
                else
                    {state=255;break;}
            case 34:
                if(*sream=='s')
                   {state=35;break;}
                else
                    {state=255;break;}
            case 35:
                if(*sream=='e')
                   {state=36;break;}
                else
                    {state=255;break;}
            case 36:
                if(*sream==' ')
                   {Resl.id=24;return Resl;}
                else
                    {state=255;break;}
            case 37:
                if(*sream=='o')
                   {state=38;break;}
                else
                    {state=255;break;}
            case 38:
                if(*sream=='t')
                   {state=39;break;}
                else
                    {state=255;break;}
            case 39:
                if(*sream=='o')
                   {state=40;break;}
                else
                    {state=255;break;}
            case 40:
                if(*sream==' ')
                   {Resl.id=25;return Resl;}
                else
                    {state=255;break;}
            default:state=255;break;
        }
        sream++;
        printf("当前状态=%d\n",state);
    }
    return Resl;
}

主函数:

#include "stdio.h"
#include "lexer.h"

int main(void)
{
    LexerPro res;
    char input[20]="while   ";
    res=Analyser(input);
    if(res.id==0)
    {
        printf("id=%d\n",res.id);
        puts("此单词为标识符");
        puts(res.Label);
    }
    printf("%s\n",input);
    if(res.id!=0)
    {
       printf("此单词为关键字,关键字索引为 %d",res.id);
    }
    return 0;
}

测试结果如下:

 

 通过上面的代码可以看到,用switch语句实现会使函数体变得很大,有的复杂状态机可能就会达到上千行,因此我们可以看到该种实现过程的缺点。但是其有点也很明显。其优点就是不浪费内存空间。

猜你喜欢

转载自www.cnblogs.com/listenscience/p/11928581.html