Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.io.IOException;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.List;
- public class CompileEngine {
- public static final String IF_TRUE = "IF_TRUE";
- public static final String IF_FALSE = "IF_FALSE";
- public static final String IF_END = "IF_END";
- public static final String WHILE_EXP = "WHILE_EXP";
- public static final String WHILE_END = "WHILE_END";
- private JackTokenizer tokenizer;
- private VMWriter vmWriter;
- private SymbolTable symbolTableClass;
- private SymbolTable symbolTableSubroutine;
- private static int indexerIf = 0;
- private static int indexerWhile = 0;
- private boolean HAS_MORE_COMMANDS = true;
- private String className;
- private static HashMap<String, String> UNIQUE_CHARS = new HashMap<String, String>() {{
- put("<", "<");
- put(">", ">");
- put("&", "&");
- put("\"", """);
- }};
- private static final List<String> Statements = Arrays.asList("if", "while", "do", "let", "return");
- private static HashMap<Character, String> OPERATORS = new HashMap<>() {{
- put('+', "add");
- put('-', "sub");
- put('*', "Math.multiply");
- put('/', "Math.divide");
- put('&', "and");
- put('|', "or");
- put('<', "lt");
- put('>', "gt");
- put('=', "eq");
- }};
- private static HashMap<Character, String> UN_OPERATORS = new HashMap<>() {{
- put('~', "not");
- put('-', "neg");
- }};
- public CompileEngine(String output, String className, JackTokenizer tokenizer) throws IOException {
- vmWriter = new VMWriter(output);
- if (tokenizer.hasMoreCommands()) {
- tokenizer.advance();
- }
- this.tokenizer = tokenizer;
- this.className = className;
- symbolTableClass = new SymbolTable();
- symbolTableSubroutine = new SymbolTable();
- compileClass();
- }
- public void close() throws IOException {
- vmWriter.close();
- }
- public void eat() throws IOException {
- if (!tokenizer.hasMoreCommands()) {
- HAS_MORE_COMMANDS = false;
- return;
- }
- tokenizer.advance();
- }
- private Symbol searchInSymbolTable(String name) {
- if (symbolTableSubroutine.contains(name)) {
- return symbolTableSubroutine.getSymbol(name);
- } else if (symbolTableClass.contains(name)) {
- return symbolTableClass.getSymbol(name);
- }
- return null;
- }
- public void compileClass() throws IOException {
- eat(); // class
- eat(); // className
- eat(); // {
- while (HAS_MORE_COMMANDS && (tokenizer.getCurrent().stringVal().equals("static") ||
- tokenizer.getCurrent().stringVal().equals("field"))) {
- compileClassVarDec();
- }
- while (HAS_MORE_COMMANDS && (tokenizer.getCurrent().stringVal().equals("constructor") ||
- tokenizer.getCurrent().stringVal().equals("function") ||
- tokenizer.getCurrent().stringVal().equals("method"))) {
- compileSubroutine();
- }
- }
- public void compileClassVarDec() throws IOException {
- String kind = tokenizer.getCurrent().keyword();
- eat();
- String type = tokenizer.getCurrent().keyword();
- eat(); //varname
- String name = tokenizer.getCurrent().stringVal();
- symbolTableClass.define(name, type, kind);
- eat();
- while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
- eat(); //","
- name = tokenizer.getCurrent().stringVal();
- symbolTableClass.define(name, type, kind);
- eat(); //varname
- }
- eat(); // ;
- }
- public void compileSubroutine() throws IOException {
- indexerIf = 0;
- indexerWhile = 0;
- symbolTableSubroutine.startSubroutine();
- String subroutineType = tokenizer.getCurrent().keyword();
- eat(); //ctor, method, function
- String returnType = tokenizer.getCurrent().keyword();
- eat();
- String subroutineName = tokenizer.getCurrent().stringVal();
- eat(); //subroutine name
- eat(); // (
- if (subroutineType.equals("method")) {
- symbolTableSubroutine.define("this", className, "argument");
- }
- int n = compileParameterList();
- String name = className + "." + subroutineName;
- eat(); // )
- eat(); // {
- while (HAS_MORE_COMMANDS && tokenizer.getCurrent().stringVal().equals("var")) {
- compileVarDec();
- }
- vmWriter.writeFunction(name, symbolTableSubroutine.varCount("local"));
- if (subroutineType.equals("constructor")) {
- vmWriter.writePush("constant", symbolTableClass.varCount("field"));
- vmWriter.writeCall("Memory.alloc", 1);
- vmWriter.writePop("pointer", 0);
- } else if (subroutineType.equals("method")) {
- vmWriter.writePush("argument", 0);
- vmWriter.writePop("pointer", 0);
- }
- compileStatements();
- eat(); // }
- }
- public int compileParameterList() throws IOException {
- int counter = 0;
- if (tokenizer.getCurrent().stringVal().equals("int") ||
- tokenizer.getCurrent().stringVal().equals("char") ||
- tokenizer.getCurrent().stringVal().equals("boolean") ||
- tokenizer.getCurrent().getType() == TokenType.identifier
- ) {
- String type = tokenizer.getCurrent().stringVal();
- eat(); //type
- String name = tokenizer.getCurrent().stringVal();
- eat(); //varname
- symbolTableSubroutine.define(name, type, "argument");
- while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
- counter++;
- eat(); // ,
- type = tokenizer.getCurrent().stringVal();
- eat(); //type
- name = tokenizer.getCurrent().stringVal();
- eat(); //varname
- symbolTableSubroutine.define(name, type, "argument");
- }
- return counter + 1;
- }
- return 0;
- }
- public void compileVarDec() throws IOException {
- // String modifier = tokenizer.getCurrent().stringVal();
- eat(); //var
- String type = tokenizer.getCurrent().stringVal();
- eat(); //type
- String name = tokenizer.getCurrent().stringVal();
- eat(); //varname
- symbolTableSubroutine.define(name, type, "local");
- while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
- eat(); // ,
- name = tokenizer.getCurrent().stringVal();
- eat(); // varname
- symbolTableSubroutine.define(name, type, "local");
- }
- eat(); //;
- }
- public void compileStatements() throws IOException {
- while (Statements.contains(tokenizer.getCurrent().stringVal())) {
- switch (tokenizer.getCurrent().keyword()) {
- case "if":
- compileIf();
- break;
- case "while":
- compileWhile();
- break;
- case "do":
- compileDo();
- break;
- case "return":
- compileReturn();
- break;
- case "let":
- compileLet();
- break;
- }
- }
- }
- public void compileDo() throws IOException {
- eat(); // keyword do
- compileTerm(); // subroutine call
- vmWriter.writePop("temp", 0);
- eat(); // ;
- }
- public void compileLet() throws IOException {
- // System.out.println(tokenizer.getCurrent().stringVal());
- eat(); // keyword let
- String name = tokenizer.getCurrent().stringVal();
- Symbol symbol = searchInSymbolTable(name);
- eat(); // identifier var
- boolean isArray = false;
- if (tokenizer.getCurrent().stringVal().equals("[")) {
- isArray = true;
- }
- if (isArray) // expression case
- {
- eat(); //symbol [
- compileExpression();
- vmWriter.writePush(symbol.getKind(), symbol.getCounter());
- vmWriter.writeArithmetic("add");
- eat(); //symbol ]
- }
- eat(); // symbol =
- compileExpression();
- if (isArray) {
- vmWriter.writePop("temp", 0);
- vmWriter.writePop("pointer", 1);
- vmWriter.writePush("temp", 0);
- vmWriter.writePop("that", 0);
- } else {
- vmWriter.writePop(symbol.getKind(), symbol.getCounter());
- }
- eat(); //;
- }
- public void compileWhile() throws IOException {
- eat(); // keyword while
- eat(); // symbol (
- vmWriter.writeLabel(WHILE_EXP + indexerWhile);
- compileExpression();
- eat(); // symbol {
- vmWriter.writeArithmetic("not");
- int indexToGo = indexerWhile;
- vmWriter.writeIf(WHILE_END + indexerWhile++);
- compileStatements();
- vmWriter.writeGoto(WHILE_EXP + indexToGo);
- vmWriter.writeLabel(WHILE_END + indexToGo);
- eat(); // symbol }
- }
- public void compileReturn() throws IOException {
- eat(); // keyword return
- if (tokenizer.getCurrent().stringVal().equals(";")) {
- vmWriter.writePush("constant", 0);
- } else {
- compileExpression();
- }
- vmWriter.writeReturn();
- eat(); // symbol ;
- }
- public void compileIf() throws IOException {
- eat(); // keyword if
- eat(); // symbol (
- compileExpression();
- eat(); // symbol {
- int indexToGo = indexerIf;
- vmWriter.writeIf(IF_TRUE + indexerIf);
- vmWriter.writeGoto(IF_FALSE + indexerIf);
- vmWriter.writeLabel(IF_TRUE + indexerIf++);
- compileStatements();
- eat(); // symbol }
- if (tokenizer.getCurrent().keyword().equals("else")) {
- vmWriter.writeGoto(IF_END + indexToGo);
- vmWriter.writeLabel(IF_FALSE + indexToGo);
- eat(); // keyword else
- eat(); //symbol {
- compileStatements();
- vmWriter.writeLabel(IF_END + indexToGo);
- eat(); //symbol }
- }
- else {
- vmWriter.writeLabel(IF_FALSE + indexToGo);
- }
- }
- public void compileExpression() throws IOException {
- compileTerm();
- while (OPERATORS.containsKey(tokenizer.getCurrent().symbol())) { //
- char op = tokenizer.getCurrent().symbol();
- eat(); //operator
- compileTerm(); //
- if (op == '*' || op == '/') {
- vmWriter.writeCall(OPERATORS.get(op), 2);
- } else {
- vmWriter.writeArithmetic(OPERATORS.get(op));
- }
- }
- if (tokenizer.getCurrent().stringVal().equals(")")) {
- eat();
- }
- }
- public void compileTerm() throws IOException {
- if (tokenizer.getCurrent().stringVal().equals("this")) {
- vmWriter.writePush("pointer", 0);
- }
- boolean isEat = true;
- if (tokenizer.getCurrent().getType() == TokenType.stringConstant ||
- tokenizer.getCurrent().getType() == TokenType.integerConstant ||
- tokenizer.getCurrent().getType() == TokenType.keyword) {
- if (tokenizer.getCurrent().getType() == TokenType.integerConstant) {
- vmWriter.writePush("constant", tokenizer.getCurrent().intVal());
- } else if (tokenizer.getCurrent().getType() == TokenType.stringConstant) {
- String str = tokenizer.getCurrent().stringVal();
- vmWriter.writePush("constant", str.length());
- vmWriter.writeCall("String.new", 1);
- for (int i = 0; i < str.length(); i++) {
- vmWriter.writePush("constant", str.charAt(i));
- vmWriter.writeCall("String.appendChar", 2);
- }
- } else {
- if (tokenizer.getCurrent().stringVal().equals("true")) {
- vmWriter.writePush("constant", 0);
- vmWriter.writeArithmetic("not");
- } else if (tokenizer.getCurrent().stringVal().equals("false") ||
- tokenizer.getCurrent().stringVal().equals("null")) {
- vmWriter.writePush("constant", 0);
- }
- }
- } else if (tokenizer.getCurrent().stringVal().equals("(")) {
- eat(); // (
- compileExpression();
- } else if (UN_OPERATORS.containsKey(tokenizer.getCurrent().symbol())) {
- char operator = tokenizer.getCurrent().symbol();
- eat(); ////
- compileTerm();
- vmWriter.writeArithmetic(UN_OPERATORS.get(operator));
- } else {
- // Token tmp = tokenizer.getCurrent();
- if (!tokenizer.hasMoreCommands()) {
- System.out.println("problem");
- }
- String name = tokenizer.getCurrent().stringVal();
- Symbol symbol = searchInSymbolTable(name);
- eat();
- if (symbol != null && tokenizer.getCurrent().symbol() != '[') {
- vmWriter.writePush(symbol.getKind(), symbol.getCounter());
- }
- int n;
- switch (tokenizer.getCurrent().symbol()) {
- case '(':
- eat(); // (
- n = compileExpressionList();
- name = className + "." + name;
- if (searchInSymbolTable(name)!=null) {
- vmWriter.writePush("pointer", 0);
- n++;
- }
- vmWriter.writeCall(name, n);
- break;
- case '[':
- eat(); // [
- compileExpression();
- vmWriter.writePush(symbol.getKind(), symbol.getCounter());
- eat(); // ]
- vmWriter.writeArithmetic("add");
- vmWriter.writePop("pointer", 1);
- vmWriter.writePush("that", 0);
- break;
- case '.':
- eat(); // .
- String method = name;
- if (symbol != null) {
- method = symbol.getType();
- }
- method += "." + tokenizer.getCurrent().stringVal();
- eat(); // subroutineName
- eat(); // (
- n = compileExpressionList();
- if (symbol != null) {
- n++;
- }
- vmWriter.writeCall(method, n);
- break;
- case ',':
- case ';':
- isEat = false;
- default:
- System.out.println(tokenizer.getCurrent().stringVal());
- break;
- }
- }
- if (isEat && !OPERATORS.containsKey(tokenizer.getCurrent().symbol()) &&
- !tokenizer.getCurrent().stringVal().equals(";") && !tokenizer.getCurrent().stringVal().equals("{")
- && !tokenizer.getCurrent().stringVal().equals(",") && !tokenizer.getCurrent().stringVal().equals("]") &&
- !OPERATORS.containsKey(tokenizer.getCurrent().symbol())) {
- eat();
- }
- }
- public int compileExpressionList() throws IOException {
- int counter = 0;
- if (tokenizer.getCurrent().getType() == TokenType.integerConstant ||
- tokenizer.getCurrent().getType() == TokenType.identifier ||
- tokenizer.getCurrent().getType() == TokenType.stringConstant ||
- tokenizer.getCurrent().getType() == TokenType.keyword ||
- UN_OPERATORS.containsKey(tokenizer.getCurrent().symbol()) ||
- tokenizer.getCurrent().symbol() == '(') { //if expression
- compileExpression(); //expression
- while (tokenizer.getCurrent().symbol() == ',') {
- eat();
- counter++;
- compileExpression();
- }
- return counter + 1;
- }
- return 0;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement