先说一些编译基础的东西,给一个源代码文件,怎么把它变成可以执行的程序,这就是编译器最基本的工作。分层的思想在计算机中有很多应用,如存储体系、网络协议、操作系统等等,在这里的应用就是把整个翻译过程分成词法分析、语法分析、语义分析,然后生成中间代码,接下来进行代码优化,最后生成可执行代码。当然现在有好多编译器生成的并不算是可执行代码,如java字节码、C#等,这里仅讨论我了解的上面这种情况――中的语法分析^_^。词法分析将一堆毫无意义的01串,(也就是你写的ASCII码源程序文件,从计算机角度看就是一个01串),识别成一个个有一定意义的符号,提供给语法分析器分析;或者从语法分析器的角度看,他没事的时候就叫词法分析器去分析出一个符号来供他分析。
到现在为止,我才写了词法分析器和一个语法分析表生成器,语法分析器还没做,不过应该简单一些。语法分析器一般分为三类:通用的语法分析器如CYK/Earley;自顶向下语法分析器;自底向上语法分析器。后两种应用比较多,下面作一个小小的比较。
自顶向下语法分析 | 自底向上语法分析 |
从根向叶构造分析树 | 从叶向根构造分析树 |
一般形式称为递归下降分析法 |
|
通过消除左递归、二义性,提取公因子,可以使用特殊的无回溯递归下降分析法(称为预测分析法) |
|
分析器使用栈以避免递归 | 同左 |
自左向右扫描输入串,每次读入一个字符 | 同左 |
分析开始时,栈里放着文法的开始符号 | 分析开始时,栈里是空的 |
每当发现一个输入符号,分析器就从栈里已有的符号出发,想办法(选产生式)来在栈顶产生一个相同的符号,然后抵消。 | 每当发现一个输入符号,分析器把它放到栈顶,然后想办法(选产生式)来归约它;如果实在没法归约,就只好先放放,读下一个输入符号放到栈顶,看看能不能单独归约或一起归约。。 |
如果输入符号分析完了,而栈也恰好为空,则为接受状态,这说明由开始符号产生的符号序列与输入串刚好能完全抵消。 | 如果输入符号分析完了,而栈里恰好只剩一个文法的开始符号,则为接受状态。意义同左。 |
相关概念: | 相关概念: LR语法分析法 |
对于自底向上分析法中的LR语法分析器,其分析过程都一样,就是读输入字符、查分析表以采取合适的行动(进栈或归约)、再读输入字符、再查表…..。不同的地方是分析表,分析表的构造方法分为简单LR方法(SLR)、规范的LR方法、向前看的LR文法(LALR),分别构造出三种不同的分析表。本着欺软怕硬的原则,我使用SLR方法来从给定文法G中构造分析表。下面先直观地看一下输入输出,然后再分析程序的结构以及代码。
输入是一个文法,保存在名为dd.txt的文本文件中,并放在程序当前目录下,其格式为:
(终结符,每行一个) ################################## (非终结符,每行一个) (产生式,每行一个) ################################## (下面的内容程序将忽略,可写一些说明) 注意: 1.务必把$作为最后一个终结符输入。 2.务必把З作为最后一个终结符输入。 3.务必把拓广的开始符号S及原来的开始符号放在非终结符的第1、2个。 4.#号分隔符是必须的:终结符、非终结符、产生式。 |
输入1与输入2文法分别为《编译原理》书中的文法4-20与文法4-19。
输入1:
= * id $ ################################## E S L R З ################################## E->S S->L=R S->R L->*R L->id R->L ################################## 注意: 1.务必把$作为最后一个终结符输入。 2.务必把З作为最后一个终结符输入。 3.务必把拓广的开始符号S及原来的开始符号放在非终结符的第1、2个。 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及原来的开始符号放在非终结符的第1、2个。 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 |