From c25b68c6b24d86b7d1169ad4ec1e619d79a2b38d Mon Sep 17 00:00:00 2001 From: student Date: Mon, 12 Feb 2018 12:01:53 -0500 Subject: Split SCLToken into subclasses. Instead of one class with a lot of fields whose state varies based on an enum, we now have a hierarchy of classes that does the same in a more obvious manner. --- base/src/bjc/dicelang/scl/BooleanSCLToken.java | 39 ++++++ base/src/bjc/dicelang/scl/FloatSCLToken.java | 41 ++++++ base/src/bjc/dicelang/scl/IntSCLToken.java | 18 +++ base/src/bjc/dicelang/scl/SCLToken.java | 140 ++++++++------------- base/src/bjc/dicelang/scl/StreamControlEngine.java | 51 ++++---- base/src/bjc/dicelang/scl/StringSCLToken.java | 46 +++++++ base/src/bjc/dicelang/scl/WordSCLToken.java | 38 ++++++ base/src/bjc/dicelang/scl/WordsSCLToken.java | 18 +++ 8 files changed, 276 insertions(+), 115 deletions(-) create mode 100644 base/src/bjc/dicelang/scl/BooleanSCLToken.java create mode 100644 base/src/bjc/dicelang/scl/FloatSCLToken.java create mode 100644 base/src/bjc/dicelang/scl/IntSCLToken.java create mode 100644 base/src/bjc/dicelang/scl/StringSCLToken.java create mode 100644 base/src/bjc/dicelang/scl/WordSCLToken.java create mode 100644 base/src/bjc/dicelang/scl/WordsSCLToken.java (limited to 'base/src') diff --git a/base/src/bjc/dicelang/scl/BooleanSCLToken.java b/base/src/bjc/dicelang/scl/BooleanSCLToken.java new file mode 100644 index 0000000..5f89ce0 --- /dev/null +++ b/base/src/bjc/dicelang/scl/BooleanSCLToken.java @@ -0,0 +1,39 @@ +package bjc.dicelang.scl; + +public class BooleanSCLToken extends SCLToken { + /* Used for BLIT */ + public boolean boolVal; + + public BooleanSCLToken(boolean val) { + super(Type.BLIT); + + boolVal = val; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + (boolVal ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + BooleanSCLToken other = (BooleanSCLToken) obj; + if (boolVal != other.boolVal) + return false; + return true; + } + + @Override + public String toString() { + return "BooleanSCLToken [boolVal=" + boolVal + "]"; + } +} diff --git a/base/src/bjc/dicelang/scl/FloatSCLToken.java b/base/src/bjc/dicelang/scl/FloatSCLToken.java new file mode 100644 index 0000000..46db4c5 --- /dev/null +++ b/base/src/bjc/dicelang/scl/FloatSCLToken.java @@ -0,0 +1,41 @@ +package bjc.dicelang.scl; + +public class FloatSCLToken extends SCLToken { + /* Used for FLIT */ + public double floatVal; + + public FloatSCLToken(double val) { + super(Type.FLIT); + + floatVal = val; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + long temp; + temp = Double.doubleToLongBits(floatVal); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + FloatSCLToken other = (FloatSCLToken) obj; + if (Double.doubleToLongBits(floatVal) != Double.doubleToLongBits(other.floatVal)) + return false; + return true; + } + + @Override + public String toString() { + return "FloatSCLToken [floatVal=" + floatVal + "]"; + } +} diff --git a/base/src/bjc/dicelang/scl/IntSCLToken.java b/base/src/bjc/dicelang/scl/IntSCLToken.java new file mode 100644 index 0000000..b90aa83 --- /dev/null +++ b/base/src/bjc/dicelang/scl/IntSCLToken.java @@ -0,0 +1,18 @@ +package bjc.dicelang.scl; + +public class IntSCLToken extends SCLToken { + /* Used for ILIT */ + public long intVal; + + /* Create a new token. */ + public IntSCLToken(final Type typ) { + super(typ); + } + + /* Create a new token. */ + public IntSCLToken(final long iVal) { + super(Type.ILIT); + + intVal = iVal; + } +} \ No newline at end of file diff --git a/base/src/bjc/dicelang/scl/SCLToken.java b/base/src/bjc/dicelang/scl/SCLToken.java index a3226e2..45e35f6 100644 --- a/base/src/bjc/dicelang/scl/SCLToken.java +++ b/base/src/bjc/dicelang/scl/SCLToken.java @@ -1,33 +1,27 @@ package bjc.dicelang.scl; -import static bjc.dicelang.Errors.ErrorKey.EK_SCL_INVTOKEN; - import java.util.HashMap; import java.util.Map; import bjc.dicelang.Errors; -import bjc.utils.funcdata.IList; import bjc.utils.parserutils.TokenUtils; +import static bjc.dicelang.Errors.ErrorKey.EK_SCL_INVTOKEN; + import static bjc.dicelang.scl.SCLToken.Type.*; +import static bjc.dicelang.scl.SCLToken.Word.*; -/* - * @TODO 10/08/17 Ben Culkin :TokenSplit - * Again with the multiple subclasses in one class. Split it so - * that each subclass only has the fields it needs. - */ public class SCLToken { + public static enum Type { /* Natural tokens. These come directly from strings */ ILIT, FLIT, BLIT, SQUOTE, DQUOTE, OBRACKET, OBRACE, SYMBOL, WORD, /* Synthetic tokens. These are produced from special tokens. */ SLIT, WORDS, ARRAY, + } - /* Word tokens These are subordinate to WORD tokens */ - /* - * @NOTE These should really be in their own enum. - */ + public static enum Word { /* Array manipulation */ MAKEARRAY, MAKEEXEC, MAKEUNEXEC, /* Stream manipulation */ @@ -36,100 +30,39 @@ public class SCLToken { STACKCOUNT, STACKEMPTY, DROP, NDROP, NIP, NNIP, } - /* The type of this token */ public SCLToken.Type type; - /* Used for ILIT */ - public long intVal; - /* Used for FLIT */ - public double floatVal; - /* Used for BLIT */ - public boolean boolVal; - /* Used for SYMBOL & SLIT */ - public String stringVal; - /* Used for WORD */ - public SCLToken tokenVal; - /* Used for WORDS & ARRAY */ - public IList tokenVals; - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ) { - type = typ; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final long iVal) { - this(typ); - - intVal = iVal; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final double dVal) { - this(typ); - - floatVal = dVal; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final boolean bVal) { - this(typ); - - boolVal = bVal; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final String sVal) { - this(typ); - - stringVal = sVal; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final SCLToken tVal) { - this(typ); - - tokenVal = tVal; - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final SCLToken.Type tVal) { - this(typ, new SCLToken(tVal)); - } - - /* Create a new token. */ - public SCLToken(final SCLToken.Type typ, final IList tVals) { - this(typ); - - tokenVals = tVals; - } - - /* Convert a string into a token. */ public static SCLToken tokenizeString(final String token) { if (litTokens.containsKey(token)) { - return new SCLToken(litTokens.get(token)); + return new IntSCLToken(litTokens.get(token)); } else if (token.startsWith("\\")) { - return new SCLToken(SYMBOL, token.substring(1)); + return new StringSCLToken(true, token.substring(1)); } else if (builtinWords.containsKey(token)) { - return new SCLToken(WORD, builtinWords.get(token)); + return new WordSCLToken(builtinWords.get(token)); } else if (token.equals("true")) { - return new SCLToken(BLIT, true); + return new BooleanSCLToken(true); } else if (token.equals("false")) { - return new SCLToken(BLIT, false); + return new BooleanSCLToken(false); } else if (TokenUtils.isInt(token)) { - return new SCLToken(ILIT, Long.parseLong(token)); + return new IntSCLToken(Long.parseLong(token)); } else if (TokenUtils.isDouble(token)) { - return new SCLToken(FLIT, Double.parseDouble(token)); + return new FloatSCLToken(Double.parseDouble(token)); } else { Errors.inst.printError(EK_SCL_INVTOKEN, token); return null; } } - /* The literal tokens. */ - private static final Map litTokens; - /* The builtin words. */ - private static final Map builtinWords; + protected static final Map litTokens; + protected static final Map builtinWords; + + protected SCLToken() { + + } + + protected SCLToken(Type typ) { + type = typ; + } static { /* Init literal tokens. */ @@ -158,4 +91,31 @@ public class SCLToken { builtinWords.put("nip", NIP); builtinWords.put("nnip", NNIP); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SCLToken other = (SCLToken) obj; + if (type != other.type) + return false; + return true; + } + + @Override + public String toString() { + return "SCLToken [type=" + type + "]"; + } } \ No newline at end of file diff --git a/base/src/bjc/dicelang/scl/StreamControlEngine.java b/base/src/bjc/dicelang/scl/StreamControlEngine.java index ec0f706..073f15e 100644 --- a/base/src/bjc/dicelang/scl/StreamControlEngine.java +++ b/base/src/bjc/dicelang/scl/StreamControlEngine.java @@ -12,6 +12,7 @@ import bjc.utils.parserutils.TokenUtils; import static bjc.dicelang.Errors.ErrorKey.*; import static bjc.dicelang.scl.SCLToken.Type.*; +import static bjc.dicelang.scl.SCLToken.Word.*; /* * @TODO 10/08/17 Ben Culkin :SCLReorg @@ -40,7 +41,7 @@ public class StreamControlEngine { * Create a new stream control engine. * * @param engine - * The engine to control. + * The engine to control. */ public StreamControlEngine(final StreamEngine engine) { eng = engine; @@ -53,7 +54,7 @@ public class StreamControlEngine { * Run a SCL program. * * @param tokens - * The program to run. + * The program to run. * * @return Whether the program executed successfully. */ @@ -61,7 +62,7 @@ public class StreamControlEngine { for (int i = 0; i < tokens.length; i++) { /* Tokenize each token. */ final String token = tokens[i]; - final SCLToken tok = SCLToken.tokenizeString(token); + final SCLToken tok = SCLToken.tokenizeString(token); if (tok == null) { System.out.printf("ERROR: Tokenization failed for '%s'\n", token); @@ -91,12 +92,12 @@ public class StreamControlEngine { return false; } final SCLToken brak = curStack.pop(); - curStack.push(new SCLToken(ARRAY, brak.tokenVals)); + curStack.push(new WordsSCLToken(true, ((WordsSCLToken) brak).tokenVals)); break; case WORD: /* Handle words. */ - if(!handleWord(tok)) { + if (!handleWord((WordSCLToken) tok)) { System.out.printf("WARNING: Execution of word '%s' failed\n", tok); } break; @@ -110,16 +111,14 @@ public class StreamControlEngine { return true; } - private boolean handleWord(final SCLToken tk) { + private boolean handleWord(final WordSCLToken tk) { boolean succ = true; /* Handle each type of word. */ - /* - * @NOTE - * This should probably use something other than a switch - * statement. + /* + * @NOTE This should probably use something other than a switch statement. */ - switch (tk.tokenVal.type) { + switch (tk.wordVal) { case NEWSTREAM: eng.newStream(); break; @@ -166,14 +165,14 @@ public class StreamControlEngine { } break; case STACKCOUNT: - curStack.push(new SCLToken(ILIT, curStack.size())); + curStack.push(new IntSCLToken(curStack.size())); break; case STACKEMPTY: - curStack.push(new SCLToken(BLIT, curStack.empty())); + curStack.push(new BooleanSCLToken(curStack.empty())); break; case DROP: if (curStack.size() == 0) { - Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.tokenVal.type.toString()); + Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.toString()); return false; } curStack.drop(); @@ -186,7 +185,7 @@ public class StreamControlEngine { break; case NIP: if (curStack.size() < 2) { - Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.tokenVal.type.toString()); + Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.toString()); return false; } curStack.nip(); @@ -198,7 +197,7 @@ public class StreamControlEngine { } break; default: - Errors.inst.printError(EK_SCL_UNWORD, tk.tokenVal.type.toString()); + Errors.inst.printError(EK_SCL_UNWORD, tk.toString()); return false; } @@ -214,7 +213,7 @@ public class StreamControlEngine { return false; } - final int n = (int) num.intVal; + final int n = (int) ((IntSCLToken) num).intVal; if (curStack.size() < n) { Errors.inst.printError(EK_SCL_SUNDERFLOW, NNIP.toString()); @@ -234,7 +233,7 @@ public class StreamControlEngine { return false; } - final int n = (int) num.intVal; + final int n = (int) ((IntSCLToken) num).intVal; if (curStack.size() < n) { Errors.inst.printError(EK_SCL_SUNDERFLOW, NDROP.toString()); @@ -278,11 +277,11 @@ public class StreamControlEngine { final IList arr = new FunctionalList<>(); - for (int i = 0; i < num.intVal; i++) { + for (int i = 0; i < ((IntSCLToken) num).intVal; i++) { arr.add(curStack.pop()); } - curStack.push(new SCLToken(ARRAY, arr)); + curStack.push(new WordsSCLToken(true, arr)); return true; } @@ -324,7 +323,7 @@ public class StreamControlEngine { return -1; } final SCLToken brak = curStack.pop(); - toks.add(new SCLToken(ARRAY, brak.tokenVals)); + toks.add(new WordsSCLToken(true, ((WordsSCLToken) brak).tokenVals)); break; default: toks.add(ntok); @@ -344,10 +343,10 @@ public class StreamControlEngine { /* Skip the closing bracket */ n += 1; - /* @NOTE - * Instead of being hardcoded, this should be a parameter. + /* + * @NOTE Instead of being hardcoded, this should be a parameter. */ - curStack.push(new SCLToken(WORDS, toks)); + curStack.push(new WordsSCLToken(false, toks)); return n; } @@ -389,7 +388,9 @@ public class StreamControlEngine { */ n += 1; - curStack.push(new SCLToken(SLIT, TokenUtils.descapeString(sb.toString()))); + String strang = TokenUtils.descapeString(sb.toString()); + + curStack.push(new StringSCLToken(false, strang)); return n; } diff --git a/base/src/bjc/dicelang/scl/StringSCLToken.java b/base/src/bjc/dicelang/scl/StringSCLToken.java new file mode 100644 index 0000000..d50b7e9 --- /dev/null +++ b/base/src/bjc/dicelang/scl/StringSCLToken.java @@ -0,0 +1,46 @@ +package bjc.dicelang.scl; + +public class StringSCLToken extends SCLToken { + /* Used for SYMBOL & SLIT */ + public String stringVal; + + public StringSCLToken(boolean isSymbol, String val) { + if(isSymbol) { + type = Type.SYMBOL; + } else { + type = Type.SLIT; + } + + stringVal = val; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((stringVal == null) ? 0 : stringVal.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + StringSCLToken other = (StringSCLToken) obj; + if (stringVal == null) { + if (other.stringVal != null) + return false; + } else if (!stringVal.equals(other.stringVal)) + return false; + return true; + } + + @Override + public String toString() { + return "StringSCLToken [stringVal=" + stringVal + "]"; + } +} diff --git a/base/src/bjc/dicelang/scl/WordSCLToken.java b/base/src/bjc/dicelang/scl/WordSCLToken.java new file mode 100644 index 0000000..46aac4f --- /dev/null +++ b/base/src/bjc/dicelang/scl/WordSCLToken.java @@ -0,0 +1,38 @@ +package bjc.dicelang.scl; + +public class WordSCLToken extends SCLToken { + public Word wordVal; + + public WordSCLToken(Word wrd) { + super(Type.WORD); + + wordVal = wrd; + } + + @Override + public String toString() { + return "WordSCLToken [wordVal=" + wordVal + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((wordVal == null) ? 0 : wordVal.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + WordSCLToken other = (WordSCLToken) obj; + if (wordVal != other.wordVal) + return false; + return true; + } +} diff --git a/base/src/bjc/dicelang/scl/WordsSCLToken.java b/base/src/bjc/dicelang/scl/WordsSCLToken.java new file mode 100644 index 0000000..81453dc --- /dev/null +++ b/base/src/bjc/dicelang/scl/WordsSCLToken.java @@ -0,0 +1,18 @@ +package bjc.dicelang.scl; + +import bjc.utils.funcdata.IList; + +public class WordsSCLToken extends SCLToken { + /* Used for WORDS & ARRAY */ + public IList tokenVals; + + public WordsSCLToken(boolean isArray, IList tokens) { + if(isArray) { + type = Type.ARRAY; + } else { + type = Type.WORDS; + } + + tokenVals = tokens; + } +} -- cgit v1.2.3