import java.io.*; import java.util.Vector; import java.util.Hashtable; import java.util.Set; /** * The SamAssembler is responsible for reading in * a file and creating a Program object that can * then be sent to the Processor for execution */ public class SamAssembler { private final static int EOF = SamTokenizer.EOF, OPERATOR = SamTokenizer.OPERATOR, INTEGER = SamTokenizer.INTEGER, WORD = SamTokenizer.WORD; /** * Assembles a new program from the file provided * @param filename The filename of the file to load * @throws FileNotFoundException if the file could not be found * @throws AssemblerException if there is an error with the instructions * @throws TokenizerException if there was an error parsing the input * @return a Program object that can be executed */ public static Program assemble(String filename) throws AssemblerException, FileNotFoundException, TokenizerException, IOException { return assemble(new SamTokenizer(filename)); } /** * Assembles a new program from the provided Reader input * The returned Program can then be sent to a Processor * for execution * @param input The reader to use for input. * @throws AssemblerException if there is an error with the instructions * @throws TokenizerException if there was an error parsing the input * @return a Program object that can be executed */ public static Program assemble(Reader input) throws AssemblerException, TokenizerException, IOException { return assemble(new SamTokenizer(input)); } /** * Assembles a new program from the tokenizer object provided. * @param in The tokenizer to use for input. * @throws AssemblerException if there is an error with the instructions * @throws TokenizerException if there was an error parsing the input * @return a Program object that can be executed. */ public static Program assemble(Tokenizer in) throws AssemblerException, TokenizerException { Program prog = new SamProgram(); SymbolTable ST = prog.getTable(); Hashtable labelReferences = new Hashtable(); do { String str = null; /*====================LABELS==================================*/ while (in.peekAtKind() != EOF && (str = in.getWord()).endsWith(":")) { /* Extract the label */ String label = str.substring(0, str.length() - 1); /* Catch Duplicates */ if (ST.resolveAddress(label) >= 0) throw new AssemblerException("Duplicate Label", in.lineNo()); /* Add to the symbol table */ ST.add(label, prog.getLength()); } /*==================== INSTRUCTIONS: NAME =======================*/ /* At this point, s should contain the instruction name */ Instruction i; try { i = (Instruction) (Class.forName(str)).newInstance(); } catch (Throwable e) { throw new AssemblerException("Unknown Instruction: " + str, in.lineNo()); } /*==================== INTEGER INSTRUCTIONS: OPERAND ============*/ /*__________Operand could be either a label or an integer._______*/ if (i instanceof SamIntInstruction) { if (in.peekAtKind() == WORD) { String label = in.getWord(); Vector references = (Vector) labelReferences.get(label); if (references == null) labelReferences.put(label, references = new Vector()); references.add (new Integer(prog.getLength())); } else ((SamIntInstruction)i).setOperand(in.getInt()); } /*===================== FLOAT INSTRUCTIONS: OPERAND =============*/ else if (i instanceof SamFloatInstruction) ((SamFloatInstruction)i).setOperand(in.getFloat()); /*===================== CHAR INSTRUCTIONS: OPERAND =============*/ else if (i instanceof SamCharInstruction) ((SamCharInstruction)i).setOperand(SamAssembler.readChar(in)); /*===================== STRING INSTRUCTIONS: OPERAND ============*/ else if (i instanceof SamStringInstruction) ((SamStringInstruction)i).setOperand(in.getWord()); /*===================== ADD INSTRUCTION TO PROGRAM ===============*/ prog.addInst(i); } while (in.peekAtKind() != EOF); /* Close Input strem */ in.close(); /* Resolve all undefined labels */ Object [] labels = labelReferences.keySet().toArray(); for (int a=0; a < labels.length; a++) { int address = ST.resolveAddress((String) labels[a]); if (address < 0) throw new AssemblerException ("Unresolved label: " + labels[a]); Vector references = (Vector) labelReferences.get(labels[a]); for (int i=0; i < references.size(); i++) { int location = ((Integer) references.get(i)).intValue(); ((SamIntInstruction) prog.getInst(location)).setOperand(address); } } /* If the generated program was null, throw an exception */ if (prog.getLength() == 0) throw new AssemblerException("Cannot assemble null program."); /* Return the program object */ return prog; } // Reads in a character private static char readChar(Tokenizer in) throws TokenizerException, AssemblerException{ if(in.peekAtKind() != Tokenizer.WORD) throw new AssemblerException("Expected Character", in.lineNo()); String s = in.getWord(); if(s.length() > 1) throw new AssemblerException("Expected Character", in.lineNo()); return s.charAt(0); } }