这些天我编写了一些语法分析器,它能够分析符合SLR,LR,LALR规范的语句。所有的类都放在syntexparse包中。算法来自与龙书。下面是一些用法。
Symbol类表示文法中的终结符和非终结符。
构造函数的第一个参数为符号名称,类型为String。第二个参数表示该符号是终结符还是非终结符,类型为boolean。
用法:对于推导规则E->E+T中文法符号E,+,T可以这样来表示
非终结符E:Symbol expression=new Symbol("E",false);
终结符+ :Symbol plus=new Symbol("+",true);
Symbol构造函数的第二个参数如果是false就表示该符号为非终结符,反之就是终结符。
非终结符的定义可以省略第二个参数,就像
非终结符T:Symbol term=new Symbol("T");
Production类表示文法的推导规则。
构造函数的第一个参数表示规则的首部,类型为Symbol。第二个参数表示规则体,类型为Symbol[]。
用法:对于上面的推导规则E->E+T可以这样表示
Production p=new Production(expression,new Symbol[]{expression,plus,term});
LRMaker类,SLRMaker类和LALRMaker类分别用来构造LR(1),SLR,LALR分析表。它们实现了ParserGenerator接口。
这是ParserGenerator接口:
package syntexparse; import java.util.*; public interface ParserGenerator{ public Map
对于如下的分析表
getGotoTable返回分析表中的goto表,getActionTable中的Action表。我使用了Map来表示分析表。表中的状态+文法符号组成的String做为键值。所以要取得状态0遇到符号c该执行的动作就调用ActionTable.get(0+"c")。
可以使用SLRGenFactory,LRGenFactory,LALRGenFactory类来生成满足ParserGenerator接口的分析表构造类LRMaker,SLRMaker和LALRMaker。例如要构造如下语法的LR分析表:
S'->S
S->CC
C->cC|d
Symbol _S=new Symbol("S'"); Symbol S=new Symbol("S"); Symbol C=new Symbol("C"); Symbol c=new Symbol("c",true); Symbol d=new Symbol("d",true); /*文法以开始符号为首部的推导规则必须放在第一个*/ Production[] productions= new Production[]{new Production(_S,new Symbol[]{S}), new Production(S ,new Symbol[]{C,C}), new Production(C ,new Symbol[]{c,C}), new Production(C ,new Symbol[]{d}) }; /*文法的开始符号必须放在第一个*/ Symbol[] symbols=new Symbol[]{_S,S,C,c,d}; LRGenFactory fa=new LRGenFactory(); ParserGenerator pg=fa.getParserGenerator(productions,symbols); //输出分析表 System.out.println(pg.getActionTable()); System.out.println(pg.getGotoTable());
Parser类用分析表来进行语法分析。
使用Parser对如下文法进行分析:
E'->E
E->E+T|T
T->T*F|F
F->(E)|id
Symbol _E=new Symbol("E'"); Symbol E=new Symbol("E"); Symbol T=new Symbol("T"); Symbol F=new Symbol("F"); Symbol plus=new Symbol("+",true); Symbol multiple=new Symbol("*",true); Symbol lp=new Symbol("(",true); Symbol rp=new Symbol(")",true); Symbol id=new Symbol("id",true); Production[] productions= new Production[]{new Production(_E,new Symbol[]{E}), new Production(E ,new Symbol[]{E,plus,T}), new Production(E ,new Symbol[]{T}), new Production(T ,new Symbol[]{T,multiple,F}), new Production(T ,new Symbol[]{F}), new Production(F ,new Symbol[]{lp,E,rp}), new Production(F ,new Symbol[]{id}) }; Symbol[] symbols=new Symbol[]{_E,E,T,F,plus,multiple,lp,rp,id}; //使用LALR语法分析 Parser lalrparser=new Parser(productions,symbols,new LALRGenFactory()); //使用LR(1)语法分析 Parser lrparser=new Parser(productions,symbols,new LRGenFactory()); //使用SLR语法分析 Parser slrparser=new Parser(productions,symbols,new SLRGenFactory()); //进行语法分析 lalrparser.parse();
对(id+id)*id$的分析过程如下:
编译包中的Parser类c:/>javac Parser.java
运行Parser类c:/>java syntexparse.Parser,用回车来隔开每个输入符号。
当遇到可规约的表达式时会输出规约步骤。
源代码可以在这里下载
csdn下载
google下载