不知不觉,写了一个编译器(二)
当我们完成了词法分析之后,就可以进行语法分析了。(词法分析链接:不知不觉,写了一个编译器(一))
语法分析的主要内容是,对于我们自己规定的语法,判断哪些token可以在一起,哪些token不行。我们在这里,主要使用建立first,follow,predict_table的方法。(针对LL文法)
对于LL文法的讲解,这里就不再赘述了。下面阐述一下,first集合,follow集合,以及predict_table的建立方法:
first 集合:
对形如U->a…的产生式(a是终结符),把a收入到First(U)中
对形入U->P…的产生式(P是非终结符),应把First(P)中的全部内容包含到First(U)中
Follow 集合:
对每一个形如“…Ua…”的组合,把a直接包含到Follow(U)中。
对形如“…UP…”(P是非终结符)的组合,把First(P)直接收入到Follow(U)中。
若S->…U,即以U结尾,则#∈Follow(U)
对形如U->…P的产生式(P是非终结符),把Follow(U)包含到Follow(P)中。
Predict_table:
Predict(U→a) =
First(a) 当First(a)不包含空
或者
First(a)-空∪Follow(U) 当First(a)包含空
下面是我们的语法:
然后是我们首先要将语法转换为LL文法,然后再构建first,follow以及predict集合:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.*;
import Scanner.Kind;
import Scanner.LexicalException;
import Scanner.Token;
import Parser.SyntaxException;
import static Scanner.Kind.*;
public class Parser {
@SuppressWarnings("serial")
public class SyntaxException extends Exception {
Token t;
public SyntaxException(Token t, String message) {
super(message);
this.t = t;
}
}
public class ThreeTuple {
public String first;
public String second;
public ThreeTuple(String a, String b) {
this.first = a;
this.second = b;
}
public void put(String a, String b) {
this.first = a;
this.second = b;
}
public String toString() {
return this.first+" "+this.second;
}
public String GetFirst() {
return this.first;
}
public String GetSecond() {
return this.second;
}
@Override
public boolean equals(Object obj) {
return obj instanceof ThreeTuple &&
this.first.equals(((ThreeTuple)obj).first) &&
this.second.equals(((ThreeTuple)obj).second);
}
@Override
public int hashCode() {
return (first!=null?first.hashCode():1)*31+(second!=null?second.hashCode():1)*31;
}
}
Scanner scanner;
Token t;
ArrayList<String> grammar;
HashSet<String> terminator;//终结符
HashMap<String, HashSet<String>> F;//建立first集合
HashMap<String, HashSet<String>> FO;//建立follow集合
String tsts;
ArrayList<Token> toks;
Parser(Scanner scanner) {
this.scanner = scanner;
t = scanner.nextToken();
tsts="";
toks=new ArrayList<Token> ();//添加已经转换为LL文法的新语法
grammar=new ArrayList<String>();
grammar.add("Program ::= IDENTIFIER Pro");
grammar.add("Pro ::= Declaration Zec | Statement Zec | ε");
grammar.add("Zec ::= SEMI Pro");
grammar.add("Declaration ::= VariableDeclaration | ImageDeclaration | SourceSinkDeclaration");
grammar.add("VariableDeclaration ::= VarType IDENTIFIER Va");
grammar.add("Va ::= OP_ASSIGN Expression | ε");
grammar.add("VarType ::= KW_int | KW_boolean");
grammar.add("SourceSinkDeclaration ::= SourceSinkType IDENTIFIER OP_ASSIGN Source");
grammar.add("Source ::= STRING_LITERAL | OP_AT Expression | IDENTIFIER");
grammar.add("SourceSinkType ::= KW_url | KW_file");
grammar.add("ImageDeclaration ::= KW_image Im IDENTIFIER Ma");
grammar.add("Im ::= LSQUARE Expression COMMA Expression RSQUARE | ε");
grammar.add("Ma ::= OP_LARROW Source | ε");
grammar.add("Statement ::= IDENTIFIER St");
grammar.add("St ::= AssignmentStatement | ImageOutStatement | ImageInStatement");
grammar.add("ImageOutStatement ::= OP_RARROW Sink");
grammar.add("Sink ::= IDENTIFIER | KW_SCREEN");
grammar.add("ImageInStatement ::= OP_LARROW Source");
grammar.add("AssignmentStatement ::= Lhs OP_ASSIGN Expression");
grammar.add("Expression ::= OrExpression E");
grammar.add("E ::= OP_Q Expression OP_COLON Expression | ε");
grammar.add("OrExpression ::= AndExpression An");
grammar.add("An ::= OP_OR AndExpression An | ε");
grammar.add("AndExpression ::= EqExpression Eq");
grammar.add("Eq ::= OP_AND EqExpression Eq | ε");
grammar.add("EqExpression ::= RelExpression Rel");
grammar.add("Rel ::= OP_EQ RelExpression Rel | OP_NEQ RelExpression Rel | ε");
grammar.add("RelExpression ::= AddExpression Add");
grammar.add("Add ::= OP_LT AddExpression Add | OP_GT AddExpression Add | OP_LE AddExpression Add | OP_GE AddExpression Add | ε");
grammar.add("AddExpression ::= MultExpression Mul");
grammar.add("Mul ::= OP_PLUS MultExpression Mul | OP_MINUS MultExpression Mul | ε");
grammar.add("MultExpression ::= UnaryExpression Unary");
grammar.add("Unary ::= OP_TIMES UnaryExpression Unary | OP_DIV UnaryExpression Unary | OP_MOD UnaryExpression Unary | ε");
grammar.add("UnaryExpression ::= OP_PLUS UnaryExpression | OP_MINUS UnaryExpression | UnaryExpressionNotPlusMinus");
grammar.add("UnaryExpressionNotPlusMinus ::= OP_EXCL UnaryExpression | Primary | IdentOrPixelSelectorExpression | KW_x | KW_y | KW_r | KW_a | KW_X | KW_Y | KW_Z | KW_A | KW_R | KW_DEF_X | KW_DEF_Y");
grammar.add("Primary ::= INTEGER_LITERAL | LPAREN Expression RPAREN | FunctionApplication | BOOLEAN_LITERAL");
grammar.add("IdentOrPixelSelectorExpression ::= IDENTIFIER Id");
grammar.add("Id ::= LSQUARE Selector RSQUARE | ε");
grammar.add("Lhs ::= LSQUARE LhsSelector RSQUARE | ε");
grammar.add("FunctionApplication ::= FunctionName Fc");
grammar.add("Fc ::= LPAREN Expression RPAREN | LSQUARE Selector RSQUARE ");
grammar.add("FunctionName ::= KW_sin | KW_cos | KW_atan | KW_abs | KW_cart_x | KW_cart_y | KW_polar_a | KW_polar_r");
grammar.add("LhsSelector ::= LSQUARE Se RSQUARE");
grammar.add("Se ::= XySelector | RaSelector");
grammar.add("XySelector ::= KW_x COMMA KW_y");
grammar.add("RaSelector ::= KW_r COMMA KW_a");
grammar.add("Selector ::= Expression COMMA Expression");
terminator=new HashSet<String> ();//添加终结符
terminator.add("IDENTIFIER"); terminator.add("INTEGER_LITERAL"); terminator.add("BOOLEAN_LITERAL");
terminator.add("STRING_LITERAL"); terminator.add("KW_x"); terminator.add("KW_X");
terminator.add("KW_y"); terminator.add("KW_Y"); terminator.add("KW_r");
terminator.add("KW_R"); terminator.add("KW_a"); terminator.add("KW_A");
terminator.add("KW_Z"); terminator.add("KW_DEF_X"); terminator.add("KW_DEF_Y");
terminator.add("KW_SCREEN"); terminator.add("KW_cart_x"); terminator.add("KW_cart_y");
terminator.add("KW_polar_a"); terminator.add("KW_polar_r"); terminator.add("KW_abs");
terminator.add("KW_sin"); terminator.add("KW_cos"); terminator.add("KW_atan");
terminator.add("KW_log"); terminator.add("KW_image"); terminator.add("KW_int");
terminator.add("KW_boolean"); terminator.add("KW_url"); terminator.add("KW_file");
terminator.add("OP_ASSIGN"); terminator.add("OP_GT"); terminator.add("OP_LT");
terminator.add("OP_EXCL"); terminator.add("OP_Q"); terminator.add("OP_COLON");
terminator.add("OP_EQ"); terminator.add("OP_NEQ"); terminator.add("OP_GE");
terminator.add("OP_LE"); terminator.add("OP_AND"); terminator.add("OP_OR");
terminator.add("OP_PLUS"); terminator.add("OP_MINUS"); terminator.add("OP_TIMES");
terminator.add("OP_DIV"); terminator.add("OP_MOD"); terminator.add("OP_POWER");
terminator.add("OP_AT"); terminator.add("OP_RARROW"); terminator.add("OP_LARROW");
terminator.add("LPAREN"); terminator.add("RPAREN"); terminator.add("LSQUARE");
terminator.add("RSQUARE"); terminator.add("SEMI"); terminator.add("COMMA");
terminator.add("ε");terminator.add("EOF");
F=new HashMap<String, HashSet<String>> ();
FO=new HashMap<String, HashSet<String>> ();
for(Token sc: scanner.tokens){
if(!sc.kind.toString().equals("EOF")) tsts=tsts+sc.kind.toString()+" ";
toks.add(sc);
}
tsts=tsts.trim();
//System.out.println("This is Parser");
}
//字符串处理,去空格等
public HashMap<String, String> Analysis(ArrayList<String> k){
HashMap<String, String> m=new HashMap<String, String>();
for(int i=0;i<k.size();i++){
String s=k.get(i);
String a[]=s.split("::=");
m.put(a[0].trim(), a[1].trim());
}
return m;
}//建立First集合
public HashSet<String> getFirst(String s,HashMap<String, String> c,HashSet<String> t){
HashSet<String> l=new HashSet<String>();
if(s.contains("|")){
String k[]=s.split("\\|");
for(int i=0;i<k.length;i++){
l.addAll(getFirst(k[i].trim(),c,t));
}
}
else{
String k[]=s.split(" ");
if(t.contains(k[0])){
l.add(k[