Advertisement
Guest User

Untitled

a guest
Jan 15th, 2020
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 16.43 KB | None | 0 0
  1. import java.io.IOException;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.List;
  5.  
  6. public class CompileEngine {
  7.     public static final String IF_TRUE = "IF_TRUE";
  8.     public static final String IF_FALSE = "IF_FALSE";
  9.     public static final String IF_END = "IF_END";
  10.     public static final String WHILE_EXP = "WHILE_EXP";
  11.     public static final String WHILE_END = "WHILE_END";
  12.  
  13.     private JackTokenizer tokenizer;
  14.     private VMWriter vmWriter;
  15.     private SymbolTable symbolTableClass;
  16.     private SymbolTable symbolTableSubroutine;
  17.     private static int indexerIf = 0;
  18.     private static int indexerWhile = 0;
  19.  
  20.     private boolean HAS_MORE_COMMANDS = true;
  21.     private String className;
  22.     private static HashMap<String, String> UNIQUE_CHARS = new HashMap<String, String>() {{
  23.         put("<", "&lt;");
  24.         put(">", "&gt;");
  25.         put("&", "&amp;");
  26.         put("\"", "&quot;");
  27.     }};
  28.     private static final List<String> Statements = Arrays.asList("if", "while", "do", "let", "return");
  29.     private static HashMap<Character, String> OPERATORS = new HashMap<>() {{
  30.         put('+', "add");
  31.         put('-', "sub");
  32.         put('*', "Math.multiply");
  33.         put('/', "Math.divide");
  34.         put('&', "and");
  35.         put('|', "or");
  36.         put('<', "lt");
  37.         put('>', "gt");
  38.         put('=', "eq");
  39.     }};
  40.     private static HashMap<Character, String> UN_OPERATORS = new HashMap<>() {{
  41.         put('~', "not");
  42.         put('-', "neg");
  43.     }};
  44.  
  45.     public CompileEngine(String output, String className, JackTokenizer tokenizer) throws IOException {
  46.         vmWriter = new VMWriter(output);
  47.         if (tokenizer.hasMoreCommands()) {
  48.             tokenizer.advance();
  49.         }
  50.         this.tokenizer = tokenizer;
  51.         this.className = className;
  52.         symbolTableClass = new SymbolTable();
  53.         symbolTableSubroutine = new SymbolTable();
  54.         compileClass();
  55.     }
  56.  
  57.     public void close() throws IOException {
  58.         vmWriter.close();
  59.  
  60.     }
  61.  
  62.     public void eat() throws IOException {
  63.         if (!tokenizer.hasMoreCommands()) {
  64.             HAS_MORE_COMMANDS = false;
  65.             return;
  66.         }
  67.         tokenizer.advance();
  68.     }
  69.  
  70.  
  71.     private Symbol searchInSymbolTable(String name) {
  72.         if (symbolTableSubroutine.contains(name)) {
  73.             return symbolTableSubroutine.getSymbol(name);
  74.         } else if (symbolTableClass.contains(name)) {
  75.             return symbolTableClass.getSymbol(name);
  76.         }
  77.         return null;
  78.  
  79.     }
  80.  
  81.     public void compileClass() throws IOException {
  82.         eat(); // class
  83.         eat(); // className
  84.         eat(); // {
  85.  
  86.         while (HAS_MORE_COMMANDS && (tokenizer.getCurrent().stringVal().equals("static") ||
  87.                 tokenizer.getCurrent().stringVal().equals("field"))) {
  88.             compileClassVarDec();
  89.         }
  90.         while (HAS_MORE_COMMANDS && (tokenizer.getCurrent().stringVal().equals("constructor") ||
  91.                 tokenizer.getCurrent().stringVal().equals("function") ||
  92.                 tokenizer.getCurrent().stringVal().equals("method"))) {
  93.             compileSubroutine();
  94.         }
  95.  
  96.     }
  97.  
  98.     public void compileClassVarDec() throws IOException {
  99.         String kind = tokenizer.getCurrent().keyword();
  100.         eat();
  101.         String type = tokenizer.getCurrent().keyword();
  102.         eat(); //varname
  103.         String name = tokenizer.getCurrent().stringVal();
  104.         symbolTableClass.define(name, type, kind);
  105.         eat();
  106.         while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
  107.             eat(); //","
  108.             name = tokenizer.getCurrent().stringVal();
  109.             symbolTableClass.define(name, type, kind);
  110.             eat(); //varname
  111.         }
  112.         eat(); // ;
  113.  
  114.     }
  115.  
  116.     public void compileSubroutine() throws IOException {
  117.         indexerIf = 0;
  118.         indexerWhile = 0;
  119.         symbolTableSubroutine.startSubroutine();
  120.         String subroutineType = tokenizer.getCurrent().keyword();
  121.         eat(); //ctor, method, function
  122.         String returnType = tokenizer.getCurrent().keyword();
  123.         eat();
  124.         String subroutineName = tokenizer.getCurrent().stringVal();
  125.         eat(); //subroutine name
  126.         eat(); // (
  127.         if (subroutineType.equals("method")) {
  128.             symbolTableSubroutine.define("this", className, "argument");
  129.         }
  130.         int n = compileParameterList();
  131.         String name = className + "." + subroutineName;
  132.  
  133.  
  134.         eat(); // )
  135.         eat(); // {
  136.         while (HAS_MORE_COMMANDS && tokenizer.getCurrent().stringVal().equals("var")) {
  137.             compileVarDec();
  138.         }
  139.         vmWriter.writeFunction(name, symbolTableSubroutine.varCount("local"));
  140.         if (subroutineType.equals("constructor")) {
  141.             vmWriter.writePush("constant", symbolTableClass.varCount("field"));
  142.             vmWriter.writeCall("Memory.alloc", 1);
  143.             vmWriter.writePop("pointer", 0);
  144.         } else if (subroutineType.equals("method")) {
  145.             vmWriter.writePush("argument", 0);
  146.             vmWriter.writePop("pointer", 0);
  147.         }
  148.         compileStatements();
  149.         eat(); // }
  150.     }
  151.  
  152.     public int compileParameterList() throws IOException {
  153.         int counter = 0;
  154.         if (tokenizer.getCurrent().stringVal().equals("int") ||
  155.                 tokenizer.getCurrent().stringVal().equals("char") ||
  156.                 tokenizer.getCurrent().stringVal().equals("boolean") ||
  157.                 tokenizer.getCurrent().getType() == TokenType.identifier
  158.         ) {
  159.             String type = tokenizer.getCurrent().stringVal();
  160.             eat(); //type
  161.             String name = tokenizer.getCurrent().stringVal();
  162.             eat(); //varname
  163.             symbolTableSubroutine.define(name, type, "argument");
  164.             while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
  165.                 counter++;
  166.                 eat(); // ,
  167.                 type = tokenizer.getCurrent().stringVal();
  168.                 eat(); //type
  169.                 name = tokenizer.getCurrent().stringVal();
  170.                 eat(); //varname
  171.                 symbolTableSubroutine.define(name, type, "argument");
  172.             }
  173.             return counter + 1;
  174.  
  175.         }
  176.         return 0;
  177.     }
  178.  
  179.     public void compileVarDec() throws IOException {
  180. //        String modifier = tokenizer.getCurrent().stringVal();
  181.         eat(); //var
  182.         String type = tokenizer.getCurrent().stringVal();
  183.         eat(); //type
  184.         String name = tokenizer.getCurrent().stringVal();
  185.         eat(); //varname
  186.         symbolTableSubroutine.define(name, type, "local");
  187.         while (HAS_MORE_COMMANDS && tokenizer.getCurrent().symbol() == ',') {
  188.             eat(); // ,
  189.             name = tokenizer.getCurrent().stringVal();
  190.             eat(); // varname
  191.             symbolTableSubroutine.define(name, type, "local");
  192.         }
  193.         eat(); //;
  194.  
  195.     }
  196.  
  197.     public void compileStatements() throws IOException {
  198.         while (Statements.contains(tokenizer.getCurrent().stringVal())) {
  199.             switch (tokenizer.getCurrent().keyword()) {
  200.                 case "if":
  201.                     compileIf();
  202.                     break;
  203.                 case "while":
  204.                     compileWhile();
  205.                     break;
  206.                 case "do":
  207.                     compileDo();
  208.                     break;
  209.                 case "return":
  210.                     compileReturn();
  211.                     break;
  212.                 case "let":
  213.                     compileLet();
  214.                     break;
  215.             }
  216.         }
  217.     }
  218.  
  219.  
  220.     public void compileDo() throws IOException {
  221.         eat(); // keyword do
  222.         compileTerm(); // subroutine call
  223.         vmWriter.writePop("temp", 0);
  224.         eat(); // ;
  225.     }
  226.  
  227.     public void compileLet() throws IOException {
  228. //        System.out.println(tokenizer.getCurrent().stringVal());
  229.         eat(); // keyword let
  230.  
  231.         String name = tokenizer.getCurrent().stringVal();
  232.         Symbol symbol = searchInSymbolTable(name);
  233.         eat(); // identifier var
  234.         boolean isArray = false;
  235.         if (tokenizer.getCurrent().stringVal().equals("[")) {
  236.             isArray = true;
  237.         }
  238.         if (isArray) // expression case
  239.         {
  240.             eat(); //symbol [
  241.             compileExpression();
  242.             vmWriter.writePush(symbol.getKind(), symbol.getCounter());
  243.             vmWriter.writeArithmetic("add");
  244.             eat(); //symbol ]
  245.         }
  246.         eat(); // symbol =
  247.         compileExpression();
  248.         if (isArray) {
  249.             vmWriter.writePop("temp", 0);
  250.             vmWriter.writePop("pointer", 1);
  251.             vmWriter.writePush("temp", 0);
  252.             vmWriter.writePop("that", 0);
  253.  
  254.         } else {
  255.             vmWriter.writePop(symbol.getKind(), symbol.getCounter());
  256.         }
  257.  
  258.         eat(); //;
  259.     }
  260.  
  261.     public void compileWhile() throws IOException {
  262.         eat(); // keyword while
  263.         eat(); // symbol (
  264.         vmWriter.writeLabel(WHILE_EXP + indexerWhile);
  265.         compileExpression();
  266.         eat(); // symbol {
  267.         vmWriter.writeArithmetic("not");
  268.         int indexToGo = indexerWhile;
  269.         vmWriter.writeIf(WHILE_END + indexerWhile++);
  270.         compileStatements();
  271.         vmWriter.writeGoto(WHILE_EXP + indexToGo);
  272.         vmWriter.writeLabel(WHILE_END + indexToGo);
  273.         eat(); // symbol }
  274.     }
  275.  
  276.     public void compileReturn() throws IOException {
  277.         eat(); // keyword return
  278.         if (tokenizer.getCurrent().stringVal().equals(";")) {
  279.             vmWriter.writePush("constant", 0);
  280.         } else {
  281.             compileExpression();
  282.         }
  283.         vmWriter.writeReturn();
  284.         eat(); // symbol ;
  285.     }
  286.  
  287.     public void compileIf() throws IOException {
  288.         eat(); // keyword if
  289.         eat(); // symbol (
  290.         compileExpression();
  291.         eat(); // symbol {
  292.         int indexToGo = indexerIf;
  293.         vmWriter.writeIf(IF_TRUE + indexerIf);
  294.         vmWriter.writeGoto(IF_FALSE + indexerIf);
  295.         vmWriter.writeLabel(IF_TRUE + indexerIf++);
  296.         compileStatements();
  297.  
  298.         eat(); // symbol }
  299.         if (tokenizer.getCurrent().keyword().equals("else")) {
  300.             vmWriter.writeGoto(IF_END + indexToGo);
  301.             vmWriter.writeLabel(IF_FALSE + indexToGo);
  302.             eat(); // keyword else
  303.             eat(); //symbol {
  304.             compileStatements();
  305.             vmWriter.writeLabel(IF_END + indexToGo);
  306.             eat(); //symbol }
  307.         }
  308.         else {
  309.             vmWriter.writeLabel(IF_FALSE + indexToGo);
  310.  
  311.         }
  312.  
  313.     }
  314.  
  315.     public void compileExpression() throws IOException {
  316.         compileTerm();
  317.         while (OPERATORS.containsKey(tokenizer.getCurrent().symbol())) { //
  318.             char op = tokenizer.getCurrent().symbol();
  319.             eat(); //operator
  320.             compileTerm(); //
  321.             if (op == '*' || op == '/') {
  322.                 vmWriter.writeCall(OPERATORS.get(op), 2);
  323.             } else {
  324.                 vmWriter.writeArithmetic(OPERATORS.get(op));
  325.             }
  326.         }
  327.         if (tokenizer.getCurrent().stringVal().equals(")")) {
  328.             eat();
  329.         }
  330.     }
  331.  
  332.     public void compileTerm() throws IOException {
  333.         if (tokenizer.getCurrent().stringVal().equals("this")) {
  334.             vmWriter.writePush("pointer", 0);
  335.         }
  336.         boolean isEat = true;
  337.         if (tokenizer.getCurrent().getType() == TokenType.stringConstant ||
  338.                 tokenizer.getCurrent().getType() == TokenType.integerConstant ||
  339.                 tokenizer.getCurrent().getType() == TokenType.keyword) {
  340.             if (tokenizer.getCurrent().getType() == TokenType.integerConstant) {
  341.                 vmWriter.writePush("constant", tokenizer.getCurrent().intVal());
  342.             } else if (tokenizer.getCurrent().getType() == TokenType.stringConstant) {
  343.                 String str = tokenizer.getCurrent().stringVal();
  344.                 vmWriter.writePush("constant", str.length());
  345.                 vmWriter.writeCall("String.new", 1);
  346.                 for (int i = 0; i < str.length(); i++) {
  347.                     vmWriter.writePush("constant", str.charAt(i));
  348.                     vmWriter.writeCall("String.appendChar", 2);
  349.                 }
  350.  
  351.             } else {
  352.                 if (tokenizer.getCurrent().stringVal().equals("true")) {
  353.                     vmWriter.writePush("constant", 0);
  354.                     vmWriter.writeArithmetic("not");
  355.                 } else if (tokenizer.getCurrent().stringVal().equals("false") ||
  356.                         tokenizer.getCurrent().stringVal().equals("null")) {
  357.                     vmWriter.writePush("constant", 0);
  358.                 }
  359.             }
  360.  
  361.         } else if (tokenizer.getCurrent().stringVal().equals("(")) {
  362.             eat(); // (
  363.             compileExpression();
  364.  
  365.         } else if (UN_OPERATORS.containsKey(tokenizer.getCurrent().symbol())) {
  366.             char operator = tokenizer.getCurrent().symbol();
  367.             eat(); ////
  368.             compileTerm();
  369.             vmWriter.writeArithmetic(UN_OPERATORS.get(operator));
  370.         } else {
  371. //            Token tmp = tokenizer.getCurrent();
  372.             if (!tokenizer.hasMoreCommands()) {
  373.                 System.out.println("problem");
  374.             }
  375.             String name = tokenizer.getCurrent().stringVal();
  376.             Symbol symbol = searchInSymbolTable(name);
  377.  
  378.             eat();
  379.             if (symbol != null && tokenizer.getCurrent().symbol() != '[') {
  380.                 vmWriter.writePush(symbol.getKind(), symbol.getCounter());
  381.             }
  382.             int n;
  383.  
  384.             switch (tokenizer.getCurrent().symbol()) {
  385.                 case '(':
  386.                     eat(); // (
  387.                     n = compileExpressionList();
  388.                     name = className + "." + name;
  389.                     if (searchInSymbolTable(name)!=null) {
  390.                         vmWriter.writePush("pointer", 0);
  391.                         n++;
  392.                     }
  393.                     vmWriter.writeCall(name, n);
  394.                     break;
  395.                 case '[':
  396.                     eat(); // [
  397.                     compileExpression();
  398.                     vmWriter.writePush(symbol.getKind(), symbol.getCounter());
  399.                     eat(); // ]
  400.                     vmWriter.writeArithmetic("add");
  401.                     vmWriter.writePop("pointer", 1);
  402.                     vmWriter.writePush("that", 0);
  403.                     break;
  404.                 case '.':
  405.                     eat(); // .
  406.                     String method = name;
  407.                     if (symbol != null) {
  408.                         method = symbol.getType();
  409.                     }
  410.                     method += "." + tokenizer.getCurrent().stringVal();
  411.                     eat(); // subroutineName
  412.                     eat(); // (
  413.                     n = compileExpressionList();
  414.                     if (symbol != null) {
  415.                         n++;
  416.                     }
  417.                     vmWriter.writeCall(method, n);
  418.                     break;
  419.                 case ',':
  420.                 case ';':
  421.                     isEat = false;
  422.                 default:
  423.                     System.out.println(tokenizer.getCurrent().stringVal());
  424.  
  425.                     break;
  426.             }
  427.         }
  428.  
  429.         if (isEat && !OPERATORS.containsKey(tokenizer.getCurrent().symbol()) &&
  430.                 !tokenizer.getCurrent().stringVal().equals(";") && !tokenizer.getCurrent().stringVal().equals("{")
  431.                 && !tokenizer.getCurrent().stringVal().equals(",") && !tokenizer.getCurrent().stringVal().equals("]") &&
  432.                 !OPERATORS.containsKey(tokenizer.getCurrent().symbol())) {
  433.             eat();
  434.         }
  435.     }
  436.  
  437.     public int compileExpressionList() throws IOException {
  438.         int counter = 0;
  439.         if (tokenizer.getCurrent().getType() == TokenType.integerConstant ||
  440.                 tokenizer.getCurrent().getType() == TokenType.identifier ||
  441.                 tokenizer.getCurrent().getType() == TokenType.stringConstant ||
  442.                 tokenizer.getCurrent().getType() == TokenType.keyword ||
  443.                 UN_OPERATORS.containsKey(tokenizer.getCurrent().symbol()) ||
  444.                 tokenizer.getCurrent().symbol() == '(') { //if expression
  445.             compileExpression(); //expression
  446.             while (tokenizer.getCurrent().symbol() == ',') {
  447.  
  448.                 eat();
  449.                 counter++;
  450.                 compileExpression();
  451.  
  452.  
  453.             }
  454.             return counter + 1;
  455.  
  456.         }
  457.         return 0;
  458.  
  459.  
  460.     }
  461.  
  462. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement