参照dragon book《编译原理》写的一个语法分析表产生器

    先说一些编译基础的东西,给一个源代码文件,怎么把它变成可以执行的程序,这就是编译器最基本的工作。分层的思想在计算机中有很多应用,如存储体系、网络协议、操作系统等等,在这里的应用就是把整个翻译过程分成词法分析、语法分析、语义分析,然后生成中间代码,接下来进行代码优化,最后生成可执行代码。当然现在有好多编译器生成的并不算是可执行代码,如java字节码、C#等,这里仅讨论我了解的上面这种情况――中的语法分析^_^。词法分析将一堆毫无意义的01串,(也就是你写的ASCII码源程序文件,从计算机角度看就是一个01串),识别成一个个有一定意义的符号,提供给语法分析器分析;或者从语法分析器的角度看,他没事的时候就叫词法分析器去分析出一个符号来供他分析。


到现在为止,我才写了词法分析器和一个语法分析表生成器,语法分析器还没做,不过应该简单一些。语法分析器一般分为三类:通用的语法分析器如CYK/Earley;自顶向下语法分析器;自底向上语法分析器。后两种应用比较多,下面作一个小小的比较。


自顶向下语法分析

自底向上语法分析

从根向叶构造分析树

从叶向根构造分析树

一般形式称为递归下降分析法

 

通过消除左递归、二义性,提取公因子,可以使用特殊的无回溯递归下降分析法(称为预测分析法)

 

分析器使用栈以避免递归

同左

自左向右扫描输入串,每次读入一个字符

同左

分析开始时,栈里放着文法的开始符号

分析开始时,栈里是空的

每当发现一个输入符号,分析器就从栈里已有的符号出发,想办法(选产生式)来在栈顶产生一个相同的符号,然后抵消。

每当发现一个输入符号,分析器把它放到栈顶,然后想办法(选产生式)来归约它;如果实在没法归约,就只好先放放,读下一个输入符号放到栈顶,看看能不能单独归约或一起归约。。

如果输入符号分析完了,而栈也恰好为空,则为接受状态,这说明由开始符号产生的符号序列与输入串刚好能完全抵消。

如果输入符号分析完了,而栈里恰好只剩一个文法的开始符号,则为接受状态。意义同左。

相关概念:
消除左递归、提取公因子。


递归下降分析法
预测分析法

相关概念:
活前缀(当前暂时归约不了,但还有希望)
句柄(可以归约的一个串)

算符优先分析法

LR语法分析法

 

对于自底向上分析法中的LR语法分析器,其分析过程都一样,就是读输入字符、查分析表以采取合适的行动(进栈或归约)、再读输入字符、再查表…..。不同的地方是分析表,分析表的构造方法分为简单LR方法(SLR)、规范的LR方法、向前看的LR文法(LALR),分别构造出三种不同的分析表。本着欺软怕硬的原则,我使用SLR方法来从给定文法G中构造分析表。下面先直观地看一下输入输出,然后再分析程序的结构以及代码。


输入是一个文法,保存在名为dd.txt的文本文件中,并放在程序当前目录下,其格式为:

(终结符,每行一个)

##################################

(非终结符,每行一个)
##################################

(产生式,每行一个)

##################################

(下面的内容程序将忽略,可写一些说明)

注意:

1.务必把$作为最后一个终结符输入。

2.务必把З作为最后一个终结符输入。

3.务必把拓广的开始符号S及原来的开始符号放在非终结符的第12个。

4.#号分隔符是必须的:终结符、非终结符、产生式。

 

输入1与输入2文法分别为《编译原理》书中的文法420与文法419

输入1

=

*

id

$

##################################

E

S

L

R

З

##################################

E->S

S->L=R

S->R

L->*R

L->id

R->L

##################################

注意:

1.务必把$作为最后一个终结符输入。

2.务必把З作为最后一个终结符输入。

3.务必把拓广的开始符号S及原来的开始符号放在非终结符的第12个。

4.#号分隔符是必须的:终结符、非终结符、产生式。

输入2

(

id

+

*

)

$

##################################

S

E

T

F

З

##################################

S->E

E->E+T

E->T

T->T*F

T->F

F->(E)

F->id

##################################

注意:

1.务必把$作为最后一个终结符输入。

2.务必把З作为最后一个终结符输入。

3.务必把拓广符号S及原来的开始符号放在非终结符的第12个。

4.#号分隔符是必须的:终结符、非终结符、产生式。

输出1

E->S

S->L=R

S->R

L->*R

L->id

R->L

*****************************************

state0:

E->.S

S->.L=R

S->.R

L->.*R

L->.id

R->.L

 

state1:

E->S.

 

state2:

S->L.=R

R->L.

 

state3:

S->R.

 

state4:

L->*.R

R->.L

L->.*R

L->.id

 

state5:

L->id.

 

state6:

S->L=.R

R->.L

L->.*R

L->.id

 

state7:

R->L.

 

state8:

L->*R.

 

state9:

S->L=R.

 

*****************************************

First collection of "=" is :=

First collection of "*" is :*

First collection of "id" is :id

First collection of "$" is :$

First collection of "E" is :*id

First collection of "S" is :*id

First collection of "L" is :*id

First collection of "R" is :*id

First collection of "З" is :

*****************************************

Follow collection of "E" is :$

Follow collection of "S" is :$

Follow collection of "L" is :=$

Follow collection of "R" is :$=

Follow collection of "З" is :

******************************************

                =    *   id    $    E    S    L    R

state0     0   s4   s5    0    0   s1   s2   s3  

state1     0    0    0    a 0    0    0    0    0  

state2    o5    0    0   r5    0    0    0    0  

state3     0    0    0   r2    0    0    0    0  

state4     0   s4   s5    0    0    0   s7   s8  

state5    r4    0    0   r4    0    0    0    0  

state6     0   s4   s5    0    0    0   s7   s9  

state7    r5    0    0   r5    0    0    0    0  

state8    r3    0    0   r3    0    0    0    0  

state9     0    0    0   r1    0    0    0    0  

 

输出2

S->E

E->E+T

E->T

T->T*F

T->F

F->(E)

F->id

*****************************************

state0:

S->.E

E->.E+T

E->.T

T->.T*F

T->.F

F->.(E)

F->.id

 

state1:

S->E.

E->E.+T

 

state2:

E->T.

T->T.*F

 

state3:

T->F.

 

state4:

F->(.E)

E->.E+T

E->.T

T->.T*F

T->.F

F->.(E)

F->.id

 

state5:

F->id.

 

state6:

E->E+.T

T->.T*F

T->.F

F->.(E)

F->.id

 

state7:

T->T*.F

F->.(E)

F->.id

 

state8:

F->(E.)

E->E.+T

 

state9:

E->E+T.

T->T.*F

 

state10:

T->T*F.

 

state11:

F->(E).

 

*****************************************

First collection of "(" is :(

First collection of "id" is :id

First collection of "+" is :+

First collection of "*" is :*

First collection of ")" is :)

First collection of "$" is :$

First collection of "S" is :(id

First collection of "E" is :(id

First collection of "T" is :(id

First collection of "F" is :(id

First collection of "З" is :

*****************************************

Follow collection of "S" is :$

Follow collection of "E" is :$+)

Follow collection of "T" is :$+*)

Follow collection of "F" is :$+*)

Follow collection of "З" is :

******************************************

               (     id    +    *    )    $    S    E    T    F

state0    s4   s5    0    0    0    0    0   s1   s2   s3  

state1     0    0   s6    0    0    a 0    0    0    0    0  

state2     0    0   r2    s7   r2   r2    0    0    0    0  

state3     0    0   r4    r4   r4   r4    0    0    0    0  

state4    s4   s5    0    0    0    0    0   s8   s2   s3  

state5     0    0   r6   r6   r6   r6    0    0    0    0  

state6    s4   s5    0    0    0    0    0    0   s9   s3  

state7    s4   s5    0    0    0    0    0    0    0   s10 

state8     0    0   s6    0   s11   0    0    0    0    0  

state9     0    0   r1   s7   r1   r1    0    0    0    0  

state10    0    0   r3   r3   r3   r3    0    0    0    0  

state11    0    0   r5   r5   r5   r5    0    0    0    0  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值