1、词法分析器生成器javacc。本文的javacc[1]为5.0版本。
Main.java和MiniJavaLexer.jj
public class Main { public static void main(String [] args) { try { new MiniJavaParser(System.in).Goal(); System.out.println("Lexical analysis successfull"); } catch (ParseException e) { System.out.println("Lexer Error : \n"+ e.toString()); } } }
options { JAVA_UNICODE_ESCAPE = true; } PARSER_BEGIN(MiniJavaParser) public class MiniJavaParser {} PARSER_END(MiniJavaParser) void Goal() : {} { ( MiniJavaToken() )* <EOF> } void MiniJavaToken(): {} { "class" | "<IDENTIFIER>" | "{" | "public" | "static" | "void" | "main" | "(" | "String" | "[" | "]" | ")" | "}" | "extends" | ";" | "return" | "," | "int" | "boolean" | "=" | "if" | "else" | "while" | "System.out.println" | "&&" | "<" | "+" | "-" | "*" | "." | "length" | "<INTEGER_LITERAL>" | "true" | "false" | "this" | "new" | "!" } SKIP:{ <("\r" | "\r\n" | "\n")> | " " | "\t" | "\n" }
$ javacc MiniJavaLexer.jj $ javac Main.java $java Main +params... 测试后满足Token的规约规则。
2、语法分析器
2.0有限自动机不能匹配括号(因为只有N状态的有限自动机不能记忆长于N的嵌套括号),所以采用文法来定义语法结构,正则表达式定义词法结构,实际上也经常使用文法定义词法结构。
2.1使用上下文无关文法而不是正则表达式,使用转换文法避免二义性。
2.2预测分析、递归下降仅限于如下文法中:每个子表达式的第一个终结符为选择产生式提供了足够多的信息。->first+follow集。
2.3first+follow集合计算方法,预测分析表,递归下降分析器,LL(K)。
X->Y1Y2Y3...Yk
first(z)=z,z为终结符
for i in [1-k]:
if Y[1...(t-1)]=null: first[Y]=first(Yt)
if Y[(t+1)...k]=null: follow(Yt)=follow(Yt)+follow(Y)
if Y(Y[(t+1)...(v-1)])=null: follow(Yt)=follow(Yt)+first(Yv)
计算出first+follow集后,可以得出预测分析表,进而完成递归下降分析器。当接受到字符串流后,可以根据预测分析表展开语法分析树。如何一个字符对应多条预测分支,则出现二义性文法。一个不包含多条预测分支的称谓LL(1)文法。存在左递归的文法不是LL(1)。因为递归下降(预测)分析器是自左而右分析,所以预测分析器会受到左递归和公共左因子的影响,通过将左递归转换为右递归和提取公共左因子可以消除影响,此时仍然有可能出现if then else的二义性问题,通过保证最近if-else最近匹配就行了。当递归下降分析器接受了错误的字符就会出现错误,错误恢复:不断跳过错误记号,直到记号与follow集合元素吻合。
2.4LR(k)通过查看栈和向前看k个输入记号决定下一步方向。k>1就因为表过于庞大不适合编译,同时k=1可以满足大多数语言的编译要求。LR(0)只需要堆栈不用向前查看记号就可以决定移进规约的操作。有时会出现移进规约操作冲突的情况,此时借助follow集合来决定表的移进规约操作,即SLR文法。LR(1)相比LR(0),粉丝表类似,但项目的概念更完善,因为LR(1)增加一个前向token,所以项目状态变多,表变大,通过合并状态来降低LR(1)的规模,这称为LALR(1)文法,LR(1)不包含移进规约冲突,但LALR(1)可能包含,但由于LALA(1)占用的内存小于LR(1),LALR(1)显得更具有标准性。
2.5面向对象风格和语法独立于解释风格(访问者模式)
面向对新风格增加一个新类型只需要增加一个类,而增加一个解释,则需要为每个类增加一个新方法。访问者模式不必重新编辑编译已经存在的类。
f
[0].http://www.cambridge.org/us/catalogue/catalogue.asp?isbn=9780521820608&ss=res
[1].javacc :https://www.ibm.com/developerworks/cn/xml/x-javacc/part1/
待续