From 6bf4b90c90f15f4ab60833bddf5b5756d1a6b1f6 Mon Sep 17 00:00:00 2001 From: Elizabeth Alexander Hunt Date: Thu, 2 Jul 2026 11:55:17 -0700 Subject: Init --- Homework/cs5300/project-two/scanner/Scanner.java | 166 +++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 Homework/cs5300/project-two/scanner/Scanner.java (limited to 'Homework/cs5300/project-two/scanner/Scanner.java') diff --git a/Homework/cs5300/project-two/scanner/Scanner.java b/Homework/cs5300/project-two/scanner/Scanner.java new file mode 100644 index 0000000..5681932 --- /dev/null +++ b/Homework/cs5300/project-two/scanner/Scanner.java @@ -0,0 +1,166 @@ +package scanner; + +import java.util.HashMap; +import java.util.Stack; + +/** + * This is the file you will modify. + */ +public class Scanner { + + //------------------------------------------------------------ + // TODO: declare the HashMaps that you will use to store + // your tables. Also declare the start state. + //------------------------------------------------------------ + + // Category table + final HashMap char2category = new HashMap<>(); + // Transition table + final HashMap> state2category2state = new HashMap<>(); + // Token type table + final HashMap state2tokenType = new HashMap<>(); + // Utility + final HashMap name2state = new HashMap<>(); + // Start state + private String s0; + + //------------------------------------------------------------ + // TODO: build your tables in the constructor and implement + // the get methods. + //------------------------------------------------------------ + + /** + * Builds the tables needed for the scanner. + */ + public Scanner(TableReader tableReader) { + // TODO: starting with the skeleton code below, build the + // classifer, transition and token type tables. You will need + // to also implement the test functions below once you have your + // tables built. + + // Build catMap, mapping a character to a category. + for (TableReader.CharCat cat : tableReader.getClassifier()) { +// System.out.println("Character " + cat.getC() + " is of category " +// + cat.getCategory()); + char2category.put(cat.getC(), cat.getCategory()); + } + + // Build the transition table. Given a state and a character category, + // give a new state. + for (TableReader.Transition t : tableReader.getTransitions()) { + String from = t.getFromStateName(); + String to = t.getToStateName(); +// System.out.println(from + " -- " + t.getCategory() +// + " --> " + to); + + if (s0 == null) + s0 = from; + + HashMap cat2state; + if (state2category2state.containsKey(from)) { + cat2state = state2category2state.get(from); + } else { + cat2state = new HashMap<>(); + state2category2state.put(from, cat2state); + } + cat2state.put(t.getCategory(), to); + } + + // Build the token types + for (TableReader.TokenType tt : tableReader.getTokens()) { +// System.out.println("State " + tt.getState() +// + " accepts with the lexeme being of type " + tt.getType()); + + state2tokenType.put(tt.getState(), tt.getType()); + } + + } + + /** + * Returns the category for c or "not in alphabet" if c has no category. Do not hardcode + * this. That is, this function should have nothing more than a table lookup + * or two. You should not have any character literals in here such as 'r' or '3'. + */ + public String getCategory(Character c) { + if (!char2category.containsKey(c)) return "not in alphabet"; + return char2category.get(c); + } + + /** + * Returns the new state given a current state and category. This models + * the transition table. Returns "error" if there is no transition. + * Do not hardcode any state names or categories. You should have only + * table lookups here. + */ + public String getNewState(String state, String category) { + if (!state2category2state.containsKey(state)) return "error"; + if (!state2category2state.get(state).containsKey(category)) return "error"; + return state2category2state.get(state).get(category); + } + + /** + * Returns the type of token corresponding to a given state. If the state + * is not accepting then return "error". + * Do not hardcode any state names or token types. + */ + public String getTokenType(String state) { + if (!state2tokenType.containsKey(state)) return "error"; + return state2tokenType.get(state); + } + + //------------------------------------------------------------ + // TODO: implement nextToken + //------------------------------------------------------------ + + /** + * Return the next token or null if there's a lexical error. + */ + public Token nextToken(ScanStream ss) { + // TODO: get a single token. This is an implementation of the nextToken + // algorithm given in class. You may *not* use TableReader in this + // function. Return null if there is a lexical error. + + String state = s0; + String lexeme = ""; + Stack stack = new Stack<>(); + String bad = "bad"; + String error = "error"; + stack.push(bad); + while (state != error) { + char c; + try { + c = ss.next(); + System.out.println("current state is " + state + " and next is " + c); + } catch(Exception e) { + state = error; + continue; + } + lexeme += c; + if (state2tokenType.containsKey(state)) + stack.clear(); + stack.push(state); + String category = char2category.get(c); + if (state2category2state.containsKey(state)) { + state = state2category2state.get(state).get(category); + } else { + state = null; + } + if (state == null) { + state = error; + } + System.out.println("Moving to state " + state); + } + while (state != bad && !state2tokenType.containsKey(state)) { + state = stack.pop(); + if (!lexeme.isEmpty()) { + lexeme = lexeme.substring(0, lexeme.length() - 1); + ss.rollback(); + } + } + if (state2tokenType.containsKey(state)) { + return new Token(state2tokenType.get(state), lexeme); + } + return null; + } + +} -- cgit v1.3