编译原理之词法分析:三个代表实现消除白空格

此文是对编译原理学习的部分总结,与一般介绍有限状态机侧重原理不同,本文侧重的是程序实现的思想。程序实现消除字符串中的多余空格,只保留一个,(\r  \n  \t  \s)。

程序根据键盘先后键入的值,判断是否该输出后键入的值,因此程序的输出有多种情况,输出选择分支时,很多人都只知道用case语句,其实可以使用函数指针数组取代之,这样程序更加简洁、清晰、强大,下面说说具体实现。

三个代表:

(1)       字符分类表:描述当前输入的字符的类型,当输入是空格时(对应ASCII码的009、010、013、032),记录为“0”,当输入为普通字符时,记录为“1”。所以整个表只有两种状态,见程序input_tab[],它由输入的字符决定;它对应着有穷自动机中的<no_ws>和<ws>。

字符分类表:input_tab[]

字符分类

非空格

空格

状态描述

<no-ws>

<ws>

chin_type

0

1

(2)       状态转换表:根据程序的要求,这里输入的字符状态chin_type只有两种,就是空格(0)和非空格(1),另外,前一次输出动作state_bf也有两种情况,所以,状态的转换对应程序中的state_tran_tab[][],它由当前状态和输入类型决定;它对应有穷自动机大圆中的“0”和“1”。它的值有两个,状态转换过程有四个。

状态转换表:state_tran_tab[][]

state_bf   \   chin_type

0 (非空格)

1 (空格)

0

0

1

1

0

1

(3)       输出动作表:用来确定当前读入的字符是否该输出,对应程序中的action_tab[][],由前一次输出的状态(state_bf)和当前状态(state_af)决定当前输出状态,所以状态有四种:字符接字符00,字符接空格01,空格接字符10,空格接空格11,只有最后一种情况不输出,这是一个函数指针数组,由前一次输入类型和当前输入类型决定;它对应着有穷自动机的output和do_nothing两个动作,但是转换过程有四种。

输出动作表:action_tab[][]

state_bf   \  state_af

0 (输出)

1 (不输出)

0

0

0

1

0

1

有穷自动机描述如下

 

其实此图对应着程序的流程图(有穷自动机就是流程图的抽象)。为了更好的解释程序,我在各个状态转换线路上标上了A/B/C/D,下面一一做出解释(A:state_bf==0,当前输入为<no_ws>,回到当前状态,输出动作为out_put; B:state_bf==0,当前输入为<ws>,转换到状态1,输出动作为out_put,因为是第一次遇到空格; D:state_bf==1,当前输入为<ws>,回到当前状态,输出动作为do_nothing,因为连续遇到空格; C:state_bf==1,当前输入为<no_ws>,转换到状态0,输出动作为out_put,因为只遇到一次空格)

程序代码如下

#include "stdio.h"

int input_tab[128]={

                     0,0,0,0,0,0,0,0,0,1,

                     0,0,0,1,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,1,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0,0,0,

                     0,0,0,0,0,0,0,0};

int state_tran_tab[2][2]={{0,1},{0,1}};

void (* action_tab[2][2])(char ch)={print,print,print,do_nothing};

void print(char ch)

{

printf("%c",ch);

}

void do_nothing(char ch)

{}

void translate(char *input)

{

    int i=0;

    int state_af=0,state_bf=0;

    int chin_type=0;

    while(input[i]!='\0')

    {

      int  chin=input[i];

      if(0<=chin<=128)

      {

           chin_type=input_tab[chin];

           state_bf=state_af;

           state_af=state_tran_tab[state_bf][chin_type];

           action_tab[state_bf][state_af](chin);

           i++;

      }

    }

}

int main()

{

char *input="a   b      c";

translate(input);

getchar();

return 0;

}

原文地址:https://www.cnblogs.com/cqpass/p/2268680.html