import java.util.*; import java.io.*; public class Hasher { protected final String IDENTIFIER = "identifier"; protected final String RESERVED_WORD = "reserved word"; protected HashMap symbolTable; protected BufferedReader keyboardReader, reservedFileReader, sourceFileReader; protected PrintWriter identifierFileWriter; /** * Initializes this Hasher object. */ public Hasher(){ } /** * Reads from the keyboard, the paths for the files that hold the reserved words * and source code, and the file that will hold the identifiers; return a reference * to the output file writer. * */ public PrintWriter openFiles() { final String SOURCE_FILE_PROMPT = "\nPlease enter the path for the file that holds the source code: "; final String RESERVED_FILE_PROMPT = "\nPlease enter the path for the file that holds the reserved words: "; final String IDENTIFIER_FILE_PROMPT = "\nPlease enter the path for the output file that will hold the identifiers: "; boolean pathsOK = false; while (!pathsOK) { try { BufferedReader keyboardReader = new BufferedReader (new InputStreamReader (System.in)); System.out.print (RESERVED_FILE_PROMPT); String reservedFilePath = keyboardReader.readLine(); reservedFileReader = new BufferedReader (new FileReader (reservedFilePath)); System.out.print (SOURCE_FILE_PROMPT); String sourceFilePath = keyboardReader.readLine(); sourceFileReader = new BufferedReader (new FileReader (sourceFilePath)); File sourceFile = new File (sourceFilePath); symbolTable = new HashMap ((int)sourceFile.length()); System.out.print (IDENTIFIER_FILE_PROMPT); String identifierFilePath = keyboardReader.readLine(); identifierFileWriter = new PrintWriter (new FileWriter (identifierFilePath)); pathsOK = true; } // try catch (IOException e) { System.out.println (e); } // catch } // while !pathsOK return identifierFileWriter; } // method openFiles /** * Reads in the reserved words and posts them to the symbol table. * */ public void readReservedWords() { String reservedWord; try { while (true) { reservedWord = reservedFileReader.readLine(); if (reservedWord == null) break; symbolTable.put (reservedWord, RESERVED_WORD); } // while not end of file } // try catch (IOException e) { System.out.println (e); } // catch } // method readReservedWords /** * Reads the source file and posts identifiers to the symbol table. * The averageTime(n, m) is O(n), and worstTime(n, m) is O(n * n), where * n is the number of identifiers and m is the size of the symbol table. */ public void readSourceCode() { final String DELIMITERS = " \'\n\r\t;:.,!?()[]@/*+-/=><{}"; String line, word; StringTokenizer tokens; int start, finish; boolean skip = false ; try { while (true) { line = sourceFileReader.readLine(); if (line == null) break; line = line.trim(); // Ignore lines beginning with "import". if (line.indexOf("import ") == 0) continue; // start another iteration of this loop // Ignore string literals. while ((start = line.indexOf ("\"")) >= 0) { finish = line.indexOf("\"", 1 + start); while (line.charAt (finish - 1) == '\\') finish = line.indexOf ("\"", finish + 1); line = line.substring(0, start) + line.substring(finish + 1); } // while line still has a string literal // Ignore // comments if ((start = line.indexOf("//")) >= 0) line = line.substring(0, start); // Ignore any line between /* and */. if ((line.indexOf ("*/") == -1) && skip) continue; // Remove substring up to */ if matching /* on earlier line. if ((start = line.indexOf("*/")) >= 0 && skip) { skip = false; line = line.substring (start + 2); } // first part of line a comment // Handle lines that have /*. while ((start = line.indexOf ("/*")) >= 0) if ((finish = line.indexOf("*/", start + 2)) >= 0) line = line.substring(0, start) + line.substring(finish + 2); else { line = line.substring(0, start); skip = true; } // matching */ not on this line // Tokenize line to find identifiers. tokens = new StringTokenizer(line, DELIMITERS); while (tokens.hasMoreTokens()) { word = tokens.nextToken(); if (Character.isLetter(word.charAt(0)) && symbolTable.get(word) == null) symbolTable.put(word, IDENTIFIER); } // while not at end of line } // while not end of file } // try catch (IOException e) { System.out.println (e); } // catch } // method readSourceCode /** * Outputs to a file all identifiers in the symbol table. * The worstTime(n, m) is O(n + m), where n is the number of identifiers * and m is the size of the symbol table. */ public void printIdentifiers() { final String HEADING = "Here are the identifiers:\n"; identifierFileWriter.println (HEADING); for (Map.Entry entry : symbolTable.entrySet()) if (entry.getValue().equals (IDENTIFIER)) identifierFileWriter.println (entry.getKey()); } // method printIdentifiers } // class Hasher