compiler

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/


待续

你可能感兴趣的:(compiler)