Ejemplo n.º 1
0
  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.");
    }
  }