// Parse a method declaration. static String getMethod(SamTokenizer f) throws TokenizerException { try { // The return type for all methods must be int. myCheck(f, "int"); // methodName stores the name of the method. String methodName = f.getWord(); if (symMap.containsKey(methodName)) throw new TokenizerException("Error: Duplicate declaration of method " + methodName); String asmCode = methodName; // The name of the method <-> index of the symbol table of the method in the symTables vector symMap.put(methodName, symTables.size()); symTables.addElement(new LinkedHashMap<String, Integer>()); // Since there cannot be another method declaration inside of a, the symbol table we are // dealing with is // always the last element of the symTables vector. symTables.lastElement().put(methodName, 0); asmCode += ":\n"; myCheck(f, '('); if (!f.check(')')) { // No SaM code generated by getFormals getFormals(f); myCheck(f, ')'); } actMap.put(methodName, params.size()); for (int i = 1; i <= params.size(); ++i) { // Add all formals to the symbol tabel symTables.lastElement().put(params.elementAt(params.size() - i), -i); } asmCode += getBody(f); // Clear the params vector and set varCounter back to 2. params.clear(); varCounter = 2; return asmCode; } catch (Exception e) { System.out.println(e.getMessage()); throw new TokenizerException("Error: Invalid method declaration."); } }
// No return value for this function. static void getFormals(SamTokenizer f) throws TokenizerException { try { // The only type for formals is int. myCheck(f, "int"); String paramName = f.getWord(); // Check if the name already exists. if (symTables.lastElement().containsKey(paramName)) throw new TokenizerException("Error: Duplicate declaration of " + paramName + "."); params.add(paramName); if (f.check(',')) { getFormals(f); } return; } catch (Exception e) { System.out.println(e.getMessage()); throw new TokenizerException("Error: Invalid formals"); } }
static String getStmt(SamTokenizer f) throws TokenizerException { try { String asmCode = ""; Boolean returnFlag1; Boolean returnFlag2; switch (f.peekAtKind()) { case WORD: { String newWord = f.getWord(); switch (newWord) { case "return": { asmCode += getExp(f); myCheck(f, ';'); // SaM code for return. asmCode += "STOREOFF -" + Integer.toString(params.size() + 1) + "\n" + "ADDSP -" + Integer.toString(varCounter - 2) + "\n" + "JUMPIND\n"; returnFlags.push(true); return asmCode; } case "if": { // Generate two valid lables for divergence. String label1 = getLabel(); String label2 = getLabel(); myCheck(f, '('); asmCode += getExp(f); myCheck(f, ')'); asmCode += ("JUMPC " + label1 + "\n"); // Buffer the statements for if condition. String tempString = getStmt(f); returnFlag1 = returnFlags.pop(); myCheck(f, "else"); asmCode += getStmt(f); returnFlag2 = returnFlags.pop(); // Manage the divergence. asmCode += ("JUMP " + label2 + "\n" + label1 + ":\n" + tempString + label2 + ":\n"); if (returnFlag1 && returnFlag2) returnFlags.push(true); else returnFlags.push(false); return asmCode; } case "while": { String label1 = getLabel(); String label2 = getLabel(); // Push the label as the return position. labels.push(label2); myCheck(f, '('); asmCode += (label1 + ":\n"); asmCode += getExp(f); asmCode += ("ISNIL\n" + "JUMPC " + label2 + "\n"); myCheck(f, ')'); // Flag indicating that we are in a while loop (possibly nested while loops.) flags.push(true); asmCode += getStmt(f); asmCode += ("JUMP " + label1 + "\n" + label2 + ":\n"); // Once finish parsing the while loop, pop out the labels and flags. labels.pop(); flags.pop(); return asmCode; } case "break": { // flags.empty() indicates that we are not currently in a while loop. if (flags.empty()) throw new TokenizerException("Error: Invalid break statement."); myCheck(f, ';'); returnFlags.push(false); // Jump to the current inner most return postion. return "JUMP " + labels.peek() + "\n"; } default: // Assign statement // Check if the variable is already defined. if (!symTables.lastElement().containsKey(newWord)) throw new TokenizerException("Error: Variable not declared."); myCheck(f, '='); asmCode += getExp(f); myCheck(f, ';'); // Get the address of the variable from the symbol table. int addr = symTables.lastElement().get(newWord); asmCode += ("STOREOFF " + Integer.toString(addr) + "\n"); returnFlags.push(false); return asmCode; } } case OPERATOR: { switch (f.getOp()) { case '{': { asmCode += getBlock(f); return asmCode; } case ';': returnFlags.push(false); return asmCode; default: throw new TokenizerException("Error: Invalid operator inside a statement."); } } default: throw new TokenizerException("Error: Invalid Statement."); } } catch (Exception e) { System.out.println(e.getMessage()); throw new TokenizerException("Error: Invalid Statement."); } }