public class P1 { /* This tests the Sym and SymTable classes. The tests have been broken up into five private helper methods for organizational purposes. */ public static void main(String[] args) { testSym(); testExceptions(); testAddDecl(); testLookup(); testPrint(); } /* Helper method to format errors properly which prints out to stderr */ private static void error(String method, String msg) { System.err.println("ERROR: " + method + ": " + msg); } private static void testSym() { /* Testing our Sym methods using the different variable types (bool, int, string) */ String[] typeList = {"bool", "int", "string"}; for (int i = 0; i < typeList.length; i++) { Sym sym = new Sym(typeList[i]); String type = sym.getType(); if (!type.equals(typeList[i])) { error("Sym.getType expecting ", type + ", but got " + typeList[i]); } type = sym.toString(); if (!type.equals(typeList[i])) { error("Sym.toString expecting ", type + ", but got " + typeList[i]); } } } private static void testExceptions() { /* This is testing that the SymTable class will throw the EmptySymTable exception when expected as well as the ability to add and remove scope, the ability to add to our SymTable with one and multiple HashMaps with addDecl */ SymTable symTable; // testing remove after calling the constructor try { symTable = new SymTable(); symTable.removeScope(); try { symTable.removeScope(); // Should throw an exception. error("SymTable.removeScope", "should throw an exception for an empty table"); } catch (EmptySymTableException e) { // Expecting } catch (Exception e) { error("SymTable.removeScope", "wrong exception for an empty table"); } } catch (EmptySymTableException e) { error("SymTable.removeScope", "EmptySymTableException thrown after calling SymTable constructor"); } catch (Exception e) { error("SymTable.removeScope", e + " thrown after calling SymTable constructor"); } // testing remove after adding/removing a map try { symTable = new SymTable(); symTable.addScope(); symTable.addScope(); symTable.addScope(); try { symTable.removeScope(); symTable.removeScope(); symTable.removeScope(); symTable.removeScope(); // Should have zero maps now try { symTable.removeScope(); // Should throw an error. error("SymTable.removeScope", "should throw an exception for an empty table"); } catch (EmptySymTableException e) { // Expecting } catch (Exception e) { error("SymTable.removeScope", "wrong exception for an empty table"); } } catch (Exception e) { error("SymTable.removeScope", "unexpected exception for a non-empty table " + e); } } catch (Exception e) { error("SymTable.addScope", "unexpected exception " + e); } // Testing to see if addDecl throws an EmptySymTableException try { symTable = new SymTable(); symTable.removeScope(); try { symTable.addDecl("name", new Sym("type")); error("SymTable.addDecl", "should throw an EmptySymTableException for an empty SymTable"); } catch (EmptySymTableException e) { // Expecting } catch (Exception e) { error("SymTable.addDecl", "wrong exception for an empty SymTable"); } } catch (Exception e) { error("SymTable.removeScope", "unexpected exception thrown for a non-empty table " + e); } // Testing to see if addDecl throws an NullPointerException symTable = new SymTable(); try { symTable.addDecl(null, new Sym("type")); error("SymTable.addDecl", "should throw an NullPointerException for 'addDecl(null, sym)'"); } catch (NullPointerException e) { // Expecting } catch (Exception e) { error("SymTable.addDecl", " wrong exception for 'addDecl(null, sym)'"); } try { symTable.addDecl("name", null); error("SymTable.addDecl", "should throw an NullPointerException for 'addDecl(name, null)'"); } catch (NullPointerException e) { // Expecting } catch (Exception e) { error("SymTable.addDecl", " wrong exception for 'addDecl(name, null)'"); } try { symTable.addDecl(null, null); error("SymTable.addDecl", "should throw an NullPointerException for 'addDecl(null, null)'"); } catch (NullPointerException e) { // Expecting } catch (Exception e) { error("SymTable.addDecl", " wrong exception for 'addDecl(null, null)'"); } } private static void testAddDecl() { /* This is testing adding to our table with not only one, but multiple HashMap, as well as with and without unique names, and makes sure that duplicate names throw the DuplicateSymException */ SymTable symTable; String name1 = "name1", name2 = "name2", name3 = "name3"; Sym sym1 = new Sym("bool"), sym2 = new Sym("int"); // Add into symTable with a single HashMap try { symTable = new SymTable(); symTable.addDecl(name1, sym1); symTable.addDecl(name2, sym2); symTable.addDecl(name3, sym1); try { symTable.addDecl(name1, sym2); error("SymTable.addDecl", "did not throw exception for duplicate name"); } catch (DuplicateSymException e) { // Expecting } catch (Exception e) { error("SymTable.addDecl", "wrong exception for duplicate name"); } } catch (Exception e) { error("symTable.addDecl", "unexpected error with a single HashMap " + e); } // Add into symTable with multiple HashMap try { symTable = new SymTable(); symTable.addDecl(name1, sym1); symTable.addScope(); symTable.addDecl(name2, sym2); symTable.addScope(); symTable.addDecl(name3, sym1); try { symTable.addDecl(name1, sym2); } catch (DuplicateSymException e) { error("SymTable.addDecl", "exception thrown when name added in another HashMap"); } try { symTable.addDecl(name3, sym2); error( "SymTable.addDecl", "exception not thrown when duplicate name added with multiple HashMaps"); } catch (DuplicateSymException e) { // Expecting } catch (Exception e) { error( "SymTable.addDecl", "wrong exception thrown when duplicate name added with multiple HashMaps"); } } catch (Exception e) { error("SymTable.addDecl", "unexpected exception with multiple HashMaps " + e); } } private static void testLookup() { /* Tests both the local and global lookup methods where both would succeed and fail with one and multiple HashMap */ Sym sym, intSym = new Sym("int"); SymTable symTable = new SymTable(); String name; // wrap the method in a try-catch block so we can catch any exceptions // thrown try { symTable = new SymTable(); symTable.removeScope(); // Testing local and global lookup with no map try { if (symTable.lookupLocal("xyz") != null) { error("symTable.lookupLocal('xyz')", "did not throw an exception for a Symtable with no maps"); } } catch (Exception e) { // Expecting } try { if (symTable.lookupGlobal("xyz") != null) { error("symTable.lookupGlobal('xyz')", "did not throw an exception for a Symtable with no maps"); } } catch (Exception e) { // Expecting } // Testing local and global lookup with a single map symTable = new SymTable(); if (symTable.lookupLocal("xyz") != null) { error("symTable.lookupLocal('xyz')", "did not return null for a Symtable lookup of xyz"); } if (symTable.lookupGlobal("xyz") != null) { error("symTable.lookupGlobal('xyz')", "did not return null for a Symtable lookup of xyz"); } // Lookup for items that have been added to the table, and make sure // there isn't an unexpected success symTable.addDecl("xyz", intSym); if (symTable.lookupLocal("xyz") == null) { error("symTable.localLookup('xyz')", "failed for table with one item unexpectedly"); //??? } if (symTable.lookupGlobal("xyz") == null) { error("symTable.localGlobal('xyz')", "failed for table with one item unexpectedly"); //??? } if (symTable.lookupLocal("x") != null) { error("symTable.localLookup('x')", "succeeded for table with one item, when the item doesn't exist"); } if (symTable.lookupGlobal("x") != null) { error("symTable.localGlobal('x')", "succeeded for table with one item, when the item doesn't exist"); } // Testing local/global lookup with multiple maps symTable.addScope(); symTable.addDecl("zyx", intSym); symTable.addScope(); Sym doubleSym = new Sym("double"); symTable.addDecl("abc", doubleSym); if (symTable.lookupLocal("xyz") != null) { error("symTable.lookupLocal('xyz')", "null not returned for value lookup of 'xyz' in third map"); } if (symTable.lookupGlobal("xyz") != intSym) { error( "symTable.lookupGlobal('xyz')", "incorrect value returned for value lookup of 'xyz' in third map"); } if (symTable.lookupLocal("zyx") != null) { error("symTable.lookupLocal('zyx')", "null not returned for value lookup of 'zyx' in second map"); } if (symTable.lookupGlobal("zyx") != intSym) { error( "symTable.lookupGlobal('zyx')", "incorrect value returned for value lookup of 'zyx' in second map"); } if (symTable.lookupLocal("abc") != doubleSym) { error("symTable.lookupLocal('abc')", "null not returned for value lookup of 'abc' in local map"); } if (symTable.lookupGlobal("abc") != doubleSym) { error( "symTable.lookupGlobal('abc')", "incorrect value returned for value lookup of 'abc' in local map"); } // testing local/global after removing a map symTable.removeScope(); if (symTable.lookupLocal("abc") != null) { error( "symTable.lookupLocal('abc')", "null not returned for 'abc' lookup, after being removed from table"); } if (symTable.lookupGlobal("abc") != null) { error( "symTable.lookupGlobal('abc')", "null not returned for 'abc' lookup, after being removed from table"); } // Adding in multiple items, looking them up localy/globaly after adding // and again after all are added symTable = new SymTable(); name = "x"; sym = new Sym("float"); for (int i = 0; i < 5; i++) { try { symTable.addDecl(name, sym); } catch (DuplicateSymException e) { error( "symTable.addDecl", "DuplicateSymException for table with one HashMap, but multiple entries"); } catch (EmptySymTableException e) { error( "symTable.addDecl", "EmptySymTableException for table with one HashMap, but multiple entries"); } if (symTable.lookupLocal(name) == null) { error("symTable.localLookup", "failure for table with one HashMap, but multiple entries"); } else if (symTable.lookupLocal(name) != sym) { error( "symTable.localLookup", "wrong value returned for table with one HashMap, but multiple entries"); } if (symTable.lookupGlobal(name) == null) { error("symTable.localGlobal", "failure for table with one HashMap, but multiple entries"); } else if (symTable.lookupGlobal(name) != sym) { error( "symTable.localGlobal", "wrong value returned for table with one HashMap, but multiple entries"); } name += "x"; } // Lookup for items that have been added to the table name = "x"; for (int i = 0; i < 5; i++) { if (symTable.lookupLocal(name) == null) { error("symTable.localLookup", "failure for table with one HashMap, but multiple entries" + "lookup after adding all values"); } if (symTable.lookupGlobal(name) == null) { error("symTable.localGlobal", "failure for table with one HashMap, but multiple entries" + "lookup after adding all values"); } name += "x"; } /* Adding a second HashMap and taking the names from the first HashMap and putting them in the second one and making sure they can be added without errors being triggered. */ symTable.addScope(); name = "x"; if (symTable.lookupGlobal(name) != sym) { error( "symTable.localGlobal", "bad value returned for name in non local HashMap of table with multiple HashMap"); } for (int i = 0; i < 5; i++) { if (symTable.lookupLocal(name) != null) { error( "symTable.localLookup", "null not returned, when expected, for name in local HashMap of table with multiple HashMap"); } if (symTable.lookupGlobal(name) != sym) { error( "symTable.localGlobal", "null returned, when unexpected, for name in non local HashMap of table with multiple HashMap"); } name += "x"; } // Adding names into the second HashMap that aren't in the first one and // making sure that they can be found name = "z"; for (int i = 0; i < 5; i++) { sym = new Sym("float"); try { symTable.addDecl(name, sym); if (symTable.lookupLocal(name) == null) { error("symTable.localLookup", "failure for adding new name in second HashMap"); } else if (symTable.lookupLocal(name) != sym) { error( "symTable.localLookup", "incorrect value returned for adding name to table with multiple HashMap"); } if (symTable.lookupGlobal(name) == null) { error("symTable.localGlobal", "failure for adding new name in second HashMap"); } else if (symTable.lookupGlobal(name) != sym) { error( "symTable.localGlobal", "incorrect value returned for adding name to table with multiple HashMap"); } } catch (DuplicateSymException e) { error( "symTable.addDecl", "DuplicateSymException for table with multiple HashMap, new name"); } catch (EmptySymTableException e) { error( "symTable.addDecl", "EmptySymTableException for table with multiple HashMap, new name"); } name += "z"; } // Symtable with 10 HashMap and 10 names in each HashMap for (int i = 0; i < 10; i++) { Integer tableInt = Integer.valueOf(i); symTable.addScope(); for (int j = 0; j < 10; j++) { Integer symInt = Integer.valueOf(j); name = tableInt.toString() + symInt.toString(); sym = new Sym("int"); try { symTable.addDecl(name, sym); if (symTable.lookupLocal(name) != sym) { error("symTable.localLookup", "failure for table with many HashMap (10)"); } if (symTable.lookupGlobal(name) != sym) { error("symTable.localGlobal", "failure for table with many HashMap (10)"); } } catch (DuplicateSymException e) { error("symTable.addDecl", "DuplicateSymException for table with many HashMap (10)"); } catch (EmptySymTableException e) { error("symTable.addDecl", "EmptySymTableException for table with many HashMap (10)"); } } } // Testing global lookup for a name from each HashMap for (int i = 0; i < 10; i++) { Integer tableInt = Integer.valueOf(i); name = tableInt.toString() + "1"; if (symTable.lookupGlobal(name) == null) { error("symTable.globalLookup", "failure for table with many HashMap (10, after all added)"); } } } catch (Exception e) { error("SymTable", "unexpected exception " + e + " using addDecl/removeScope when testing lookup"); } } private static void testPrint() { /* Tests the print function by calling it with no HashMap, a single HashMap, and multiple HashMap. */ SymTable symTable = new SymTable(); try { symTable.print(); try { symTable.addDecl("x", new Sym("int")); symTable.addDecl("y", new Sym("bool")); symTable.addScope(); symTable.addDecl("z", new Sym("void")); symTable.addScope(); symTable.addDecl("q", new Sym("double")); } catch (Exception e) { error("SymTable.addDecl, unexpected exception: ", e.toString()); } symTable.print(); for (int i = 0; i < 3; i++) { try { symTable.removeScope(); } catch (Exception e) { error("SymTable.removeScope, unexpected exception: ", e.toString()); } symTable.print(); } } catch (Exception e) { error("SymTable.print, unexpected exception: ", e.toString()); } } }