diff options
| author | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 16:38:35 -0300 |
|---|---|---|
| committer | Benjamin J. Culkin <bjculkin@mix.wvu.edu> | 2017-10-08 16:38:35 -0300 |
| commit | 054643900e7b857cafe123b0b4c03f10a95520ed (patch) | |
| tree | c289fc397fe79ea0a6792e3f2f39a05ed1315936 /dice-lang/src | |
| parent | f40e5a873420d70d01ff7e01b77bdbd64faab00e (diff) | |
Update
Diffstat (limited to 'dice-lang/src')
| -rw-r--r-- | dice-lang/src/bjc/dicelang/DiceLangConsole.java | 144 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/DiceLangEngine.java | 308 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/Errors.java | 30 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/Evaluator.java | 20 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/Tokenizer.java | 71 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/dice/CompoundDie.java | 27 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/dice/CompoundingDie.java | 31 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/dice/DiceBox.java | 131 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/expr/Ezpr.java | 256 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java | 20 | ||||
| -rw-r--r-- | dice-lang/src/bjc/dicelang/scl/StreamEngine.java | 62 |
11 files changed, 479 insertions, 621 deletions
diff --git a/dice-lang/src/bjc/dicelang/DiceLangConsole.java b/dice-lang/src/bjc/dicelang/DiceLangConsole.java index 29b6f1a..7cd6bb5 100644 --- a/dice-lang/src/bjc/dicelang/DiceLangConsole.java +++ b/dice-lang/src/bjc/dicelang/DiceLangConsole.java @@ -19,10 +19,11 @@ import jline.Terminal; * */ public class DiceLangConsole { + /* The number of commands executed so far. */ private int commandNumber; - + /* The engine that executes commands. */ private final DiceLangEngine eng; - + /* The place to read input from. */ private ConsoleReader read; /** @@ -33,13 +34,10 @@ public class DiceLangConsole { */ public DiceLangConsole(final String[] args) { commandNumber = 0; - eng = new DiceLangEngine(); - if (!CLIArgsParser.parseArgs(args, eng)) { System.exit(1); } - Terminal.setupTerminal(); } @@ -47,9 +45,7 @@ public class DiceLangConsole { * Run the console. */ public void run() { - /* - * Set up console. - */ + /* Set up console. */ try { read = new ConsoleReader(); } catch (final IOException ioex) { @@ -58,12 +54,9 @@ public class DiceLangConsole { } System.out.println("dice-lang v0.2"); - String comm = null; - /* - * Read initial command. - */ + /* Read initial command. */ try { comm = read.readLine(String.format("(%d) dice-lang> ", commandNumber)); } catch (final IOException ioex) { @@ -71,35 +64,22 @@ public class DiceLangConsole { return; } - /* - * Run commands. - */ + /* Run commands. */ while (!comm.equals("quit") && !comm.equals("exit")) { if (comm.startsWith("pragma")) { - /* - * Run pragmas. - */ + /* Run pragmas. */ final boolean success = handlePragma(comm.substring(7)); - if (success) { - System.out.println("Pragma completed succesfully"); - } else { - System.out.println("Pragma execution failed"); - } + if (success) System.out.println("Pragma completed succesfully"); + else System.out.println("Pragma execution failed"); } else { - /* - * Run commands. - */ - if(eng.debugMode) - System.out.printf("\tRaw command: %s\n", comm); + /* Run commands. */ + if(eng.debugMode) System.out.printf("\tRaw command: %s\n", comm); final boolean success = eng.runCommand(comm); - if (success) { - System.out.println("Command completed succesfully"); - } else { - System.out.println("Command execution failed"); - } + if (success) System.out.println("Command completed succesfully"); + else System.out.println("Command execution failed"); commandNumber += 1; } @@ -114,23 +94,15 @@ public class DiceLangConsole { } private boolean handlePragma(final String pragma) { - if(eng.debugMode) - System.out.println("\tRaw pragma: " + pragma); + if(eng.debugMode) System.out.println("\tRaw pragma: " + pragma); - /* - * Grab the name from the arguments. - */ + /* Grab the name from the arguments. */ String pragmaName = null; final int firstIndex = pragma.indexOf(' '); - /* - * Handle argless pragmas. - */ - if (firstIndex == -1) { - pragmaName = pragma; - } else { - pragmaName = pragma.substring(0, firstIndex); - } + /* Handle argless pragmas. */ + if (firstIndex == -1) pragmaName = pragma; + else pragmaName = pragma.substring(0, firstIndex); /* * Run pragmas. @@ -139,25 +111,19 @@ public class DiceLangConsole { case "debug": System.out.println("\tDebug mode is now " + eng.toggleDebug()); break; - case "postfix": System.out.println("\tPostfix mode is now " + eng.togglePostfix()); break; - case "prefix": System.out.println("\tPrefix mode is now " + eng.togglePrefix()); break; - case "stepeval": System.out.println("\tStepeval mode is now" + eng.toggleStepEval()); break; - case "define": return defineMode(pragma.substring(7)); - case "help": return helpMode(pragma.substring(5)); - default: Errors.inst.printError(EK_CONS_INVPRAG, pragma); return false; @@ -166,62 +132,52 @@ public class DiceLangConsole { return true; } - /* - * Run a help mode. - */ + /* Run a help mode. */ private static boolean helpMode(final String pragma) { switch (pragma.trim()) { case "help": System.out.println("\tGet help on pragmas"); break; - case "debug": System.out.println("\tToggle debug mode. (Output stage results)"); break; - case "postfix": System.out.println("\tToggle postfix mode. (Don't shunt tokens)"); break; - case "prefix": System.out.println("\tToggle prefix mode. (Reverse token order instead of shunting)"); break; - case "stepeval": System.out.println("\tToggle stepeval mode. (Print out evaluation progress)"); break; - case "define": System.out.println("\tAdd a macro rewrite directive."); System.out.println("\tdefine <priority> <type> <recursion> <guard> <circular> <patterns>..."); break; - default: System.out.println("\tNo help available for pragma " + pragma); } - // Help always works + /* Help always works */ return true; } - /* - * Matches slash-delimited strings (like /text/ or /text\/text/). - */ + /* Matches slash-delimited strings (like /text/ or /text\/text/). */ private final Pattern slashPattern = Pattern.compile("/((?:\\\\.|[^/\\\\])*)/"); + /* Parse a define macro. */ private boolean defineMode(final String defineText) { - /* - * Grab all of the separator spaces. - */ - final int firstIndex = defineText.indexOf(' '); - final int secondIndex = defineText.indexOf(' ', firstIndex + 1); - final int thirdIndex = defineText.indexOf(' ', secondIndex + 1); - final int fourthIndex = defineText.indexOf(' ', thirdIndex + 1); - final int fifthIndex = defineText.indexOf(' ', fourthIndex + 1); - final int sixthIndex = defineText.indexOf(' ', fifthIndex + 1); - - /* - * Error if we got something we didn't need. + /* Grab all of the separator spaces. */ + final int firstIndex = defineText.indexOf(' '); + final int secondIndex = defineText.indexOf(' ', firstIndex + 1); + final int thirdIndex = defineText.indexOf(' ', secondIndex + 1); + final int fourthIndex = defineText.indexOf(' ', thirdIndex + 1); + final int fifthIndex = defineText.indexOf(' ', fourthIndex + 1); + final int sixthIndex = defineText.indexOf(' ', fifthIndex + 1); + + /* + * Error if we got something we didn't need, or didn't get + * something we need. */ if (firstIndex == -1) { Errors.inst.printError(EK_CONS_INVDEFINE, "(no priority)"); @@ -244,7 +200,6 @@ public class DiceLangConsole { } final int priority = Integer.parseInt(defineText.substring(0, firstIndex)); - final String defineType = defineText.substring(firstIndex + 1, secondIndex); Define.Type type; @@ -254,36 +209,31 @@ public class DiceLangConsole { case "line": type = Define.Type.LINE; break; - case "token": type = Define.Type.TOKEN; break; - case "subline": type = Define.Type.LINE; subMode = true; break; - case "subtoken": type = Define.Type.TOKEN; subMode = true; break; - default: Errors.inst.printError(EK_CONS_INVDEFINE, "(unknown type)"); return false; } - final boolean doRecur = defineText.substring(secondIndex + 1, - thirdIndex).equalsIgnoreCase("true"); - final boolean hasGuard = defineText.substring(thirdIndex + 1, - fourthIndex).equalsIgnoreCase("true"); - final boolean isCircular = defineText.substring(thirdIndex + 1, - fourthIndex).equalsIgnoreCase("true"); + final boolean doRecur = defineText.substring(secondIndex + 1, thirdIndex) + .equalsIgnoreCase("true"); + final boolean hasGuard = defineText.substring(thirdIndex + 1, fourthIndex) + .equalsIgnoreCase("true"); + final boolean isCircular = defineText.substring(thirdIndex + 1, fourthIndex) + .equalsIgnoreCase("true"); final String pats = defineText.substring(fifthIndex + 1).trim(); final Matcher patMatcher = slashPattern.matcher(pats); - String guardPattern = null; if (hasGuard) { @@ -291,7 +241,6 @@ public class DiceLangConsole { Errors.inst.printError(EK_CONS_INVDEFINE, "(no guard pattern)"); return false; } - guardPattern = patMatcher.group(1); } @@ -302,22 +251,18 @@ public class DiceLangConsole { final String searchPattern = patMatcher.group(1); final List<String> replacePatterns = new LinkedList<>(); - while (patMatcher.find()) { replacePatterns.add(patMatcher.group(1)); } - final Define dfn = new Define(priority, subMode, doRecur, isCircular, guardPattern, - searchPattern, - replacePatterns); + final Define dfn = new Define(priority, subMode, doRecur, + isCircular, guardPattern, searchPattern, + replacePatterns); if (dfn.inError) return false; - if (type == Define.Type.LINE) { - eng.addLineDefine(dfn); - } else { - eng.addTokenDefine(dfn); - } + if (type == Define.Type.LINE) eng.addLineDefine(dfn); + else eng.addTokenDefine(dfn); return true; } @@ -330,7 +275,6 @@ public class DiceLangConsole { */ public static void main(final String[] args) { final DiceLangConsole console = new DiceLangConsole(args); - console.run(); } } diff --git a/dice-lang/src/bjc/dicelang/DiceLangEngine.java b/dice-lang/src/bjc/dicelang/DiceLangEngine.java index 0ac088e..158239e 100644 --- a/dice-lang/src/bjc/dicelang/DiceLangEngine.java +++ b/dice-lang/src/bjc/dicelang/DiceLangEngine.java @@ -13,6 +13,7 @@ import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,7 +34,7 @@ import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter; * @author Ben Culkin */ public class DiceLangEngine { - public boolean debug = true; + private static final Logger LOG = Logger.getLogger(DiceLangEngine.class.getName()); /* * The random fields that are package private instead of private-private @@ -41,104 +42,69 @@ public class DiceLangEngine { * them. */ - /* - * Split tokens around operators with regex - */ + /* Split tokens around operators with regex */ ConfigurableTokenSplitter opExpander; - /* - * ID for generation. - */ + /* ID for generation. */ int nextLiteral; - /* - * Debug indicator. - */ + /* Debug indicator. */ public boolean debugMode; - /* - * Should we do shunting? - */ + /* Should we do shunting? */ private boolean postfixMode; - /* - * Should we reverse the token stream? - */ + /* Should we reverse the token stream? */ private boolean prefixMode; - /* - * Should we do step-by-step evaluation? - */ + /* Should we do step-by-step evaluation? */ private boolean stepEval; - /* - * Shunter for token shunting. - */ + /* Shunter for token shunting. */ Shunter shunt; - /* - * Tokenizer for tokenizing. - */ + /* Tokenizer for tokenizing. */ Tokenizer tokenzer; - /* - * Parser for tree construction. - */ + /* Parser for tree construction. */ Parser parsr; - /* - * Evaluator for evaluating. - */ + /* Evaluator for evaluating. */ Evaluator eval; - /* - * Tables for various things. - */ + /* Tables for various things. */ /** * The symbol table. */ public final IMap<Integer, String> symTable; + /* String literal tables */ private final IMap<Integer, String> stringLits; private final IMap<String, String> stringLiterals; - /* - * Lists of defns. - */ + /* Lists of defns. */ private final IList<Define> lineDefns; private final IList<Define> tokenDefns; - /* - * Are defns sorted by priority? - */ + /* Are defns currently sorted by priority? */ private boolean defnsSorted; - /* - * Stream engine for processing streams. - */ + /* Stream engine for processing streams. */ StreamEngine streamEng; /** * Create a new DiceLang engine. */ public DiceLangEngine() { - /* - * Initialize defns. - */ + /* Initialize defns. */ lineDefns = new FunctionalList<>(); tokenDefns = new FunctionalList<>(); defnsSorted = true; - /* - * Initialize tables. - */ + /* Initialize tables. */ symTable = new FunctionalMap<>(); stringLits = new FunctionalMap<>(); stringLiterals = new FunctionalMap<>(); - /* - * Initialize operator expansion list. - */ + /* Initialize operator expander. */ opExpander = new ConfigurableTokenSplitter(true); - opExpander.addMultiDelimiters("(", ")"); opExpander.addMultiDelimiters("[", "]"); opExpander.addMultiDelimiters("{", "}"); - opExpander.addSimpleDelimiters(":="); opExpander.addSimpleDelimiters("=>"); opExpander.addSimpleDelimiters("//"); @@ -150,22 +116,16 @@ public class DiceLangEngine { opExpander.addSimpleDelimiters("/"); opExpander.compile(); - /* - * Initialize literal IDs - */ + /* Initialize literal IDs */ nextLiteral = 1; - /* - * Initial mode settings. - */ + /* Initial mode settings. */ debugMode = true; postfixMode = false; prefixMode = false; stepEval = false; - /* - * Create components. - */ + /* Create components. */ streamEng = new StreamEngine(this); shunt = new Shunter(); tokenzer = new Tokenizer(this); @@ -251,9 +211,7 @@ public class DiceLangEngine { return stepEval; } - /* - * Matches double-angle bracketed strings. - */ + /* Matches double-angle bracketed strings. */ private final Pattern nonExpandPattern = Pattern.compile("<<([^\\>]*(?:\\>(?:[^\\>])*)*)>>"); @@ -266,66 +224,44 @@ public class DiceLangEngine { * @return Whether or not the command ran successfully */ public boolean runCommand(final String command) { - /* - * Preprocess the command into tokens - */ + /* Preprocess the command into tokens */ final IList<String> preprocessedTokens = preprocessCommand(command); - if (preprocessedTokens == null) return false; - /* - * Lex the string tokens into token-tokens - */ + /* Lex the string tokens into token-tokens */ final IList<Token> lexedTokens = lexTokens(preprocessedTokens); - if (lexedTokens == null) return false; - /* - * Parse the tokens into an AST forest - */ + /* Parse the tokens into an AST forest */ final IList<ITree<Node>> astForest = new FunctionalList<>(); final boolean succ = Parser.parseTokens(lexedTokens, astForest); - if (!succ) return false; - /* - * Evaluate the AST forest - */ + /* Evaluate the AST forest */ evaluateForest(astForest); - return true; } - /* - * Lex string tokens into token-tokens - */ + /* Lex string tokens into token-tokens */ private IList<Token> lexTokens(final IList<String> preprocessedTokens) { final IList<Token> lexedTokens = new FunctionalList<>(); for (final String token : preprocessedTokens) { String newTok = token; - /* - * Apply token defns - */ + /* Apply token defns */ for (final Define dfn : tokenDefns.toIterable()) { newTok = dfn.apply(newTok); } - /* - * Lex the token - */ + /* Lex the token */ final Token tk = tokenzer.lexToken(token, stringLiterals); - + if(debugMode) LOG.finer(String.format("lexed token: %s\n", tk)); if (tk == null) { - /* - * Ignore blank tokens - */ + /* Ignore blank tokens */ continue; } else if (tk == Token.NIL_TOKEN) - /* - * Fail on bad tokens - */ + /* Fail on bad tokens */ return null; else { lexedTokens.add(tk); @@ -333,56 +269,58 @@ public class DiceLangEngine { } if (debugMode) { - System.out.printf("\tCommand after tokenization: %s\n", lexedTokens.toString()); + String msg = String.format("\tCommand after tokenization: %s\n", lexedTokens.toString()); + LOG.fine(msg); + System.out.print(msg); } - /* - * Preshunt preshunt-marked groups of tokens - */ + /* Preshunt preshunt-marked groups of tokens */ IList<Token> shuntedTokens = lexedTokens; final IList<Token> preparedTokens = new FunctionalList<>(); boolean succ = removePreshuntTokens(lexedTokens, preparedTokens); - if (!succ) return null; if (debugMode && !postfixMode) { - System.out.printf("\tCommand after pre-shunter removal: %s\n", preparedTokens.toString()); + String msg = String.format("\tCommand after pre-shunter removal: %s\n", preparedTokens.toString()); + LOG.fine(msg); + System.out.print(msg); } if (!postfixMode && !prefixMode) { - /* - * Shunt the tokens - */ + /* Shunt the tokens */ shuntedTokens = new FunctionalList<>(); succ = shunt.shuntTokens(preparedTokens, shuntedTokens); if (!succ) return null; } else if (prefixMode) { - /* - * Reverse directional tokens - */ + /* Reverse directional tokens */ preparedTokens.reverse(); shuntedTokens = preparedTokens.map(this::reverseToken); } if (debugMode && !postfixMode) { - System.out.printf("\tCommand after shunting: %s\n", shuntedTokens.toString()); + String msg = String.format("\tCommand after shunting: %s\n", shuntedTokens.toString()); + LOG.fine(msg); + System.out.print(msg); } - /* - * Expand token groups - */ + /* Expand token groups */ final IList<Token> readyTokens = shuntedTokens.flatMap(tk -> { - if (tk.type == Token.Type.TOKGROUP) - return tk.tokenValues; - else if (tk.type == Token.Type.TAGOP || tk.type == Token.Type.TAGOPR) + if (tk.type == Token.Type.TOKGROUP || + tk.type == Token.Type.TAGOP || + tk.type == Token.Type.TAGOPR ) { + LOG.finer(String.format("Expanding token group to: %s\n", tk.tokenValues.toString())); return tk.tokenValues; - else return new FunctionalList<>(tk); + } else { + return new FunctionalList<>(tk); + } }); if (debugMode && !postfixMode) { - System.out.printf("\tCommand after re-preshunting: %s\n", readyTokens.toString()); + String msg = String.format("\tCommand after re-preshunting: %s\n", readyTokens.toString()); + LOG.fine(msg); + System.out.print(msg); } return readyTokens; @@ -397,53 +335,40 @@ public class DiceLangEngine { switch (tk.type) { case OBRACE: return new Token(CBRACE, tk.intValue); - case OPAREN: return new Token(CPAREN, tk.intValue); - case OBRACKET: return new Token(CBRACKET, tk.intValue); - case CBRACE: return new Token(OBRACE, tk.intValue); - case CPAREN: return new Token(OPAREN, tk.intValue); - case CBRACKET: return new Token(OBRACKET, tk.intValue); - default: return tk; } } - /* - * Preprocess a command into a list of string tokens. - */ + /* Preprocess a command into a list of string tokens. */ private IList<String> preprocessCommand(final String command) { - /* - * Sort the defines if they aren't sorted - */ + /* Sort the defines if they aren't sorted */ if (!defnsSorted) { sortDefns(); } - /* - * Run the tokens through the stream engine - */ + /* Run the tokens through the stream engine */ final IList<String> streamToks = new FunctionalList<>(); final boolean succ = streamEng.doStreams(command.split(" "), streamToks); - if (!succ) return null; - /* - * Apply line defns - */ + /* Apply line defns */ String newComm = ListUtils.collapseTokens(streamToks, " "); if (debugMode) { - System.out.println("\tCommand after stream commands: " + newComm); + String msg = String.format("\tCommand after stream commands: %s\n", newComm); + LOG.fine(msg); + System.out.print(msg); } for (final Define dfn : lineDefns.toIterable()) { @@ -451,23 +376,19 @@ public class DiceLangEngine { } if (debugMode) { - System.out.println("\tCommand after line defines: " + newComm); + String msg = String.format("\tCommand after line defines: %s\n", newComm); + LOG.fine(msg); + System.out.print(msg); } - /* - * Remove string literals. - */ + /* Remove string literals. */ final List<String> destringedParts = TokenUtils.removeDQuotedStrings(newComm); final StringBuffer destringedCommand = new StringBuffer(); for (final String part : destringedParts) { - /* - * Handle string literals - */ + /* Handle string literals */ if (part.startsWith("\"") && part.endsWith("\"")) { - /* - * Get the actual string. - */ + /* Get the actual string. */ final String litName = "stringLiteral" + nextLiteral; final String litVal = part.substring(1, part.length() - 1); @@ -475,12 +396,14 @@ public class DiceLangEngine { * Insert the string with its escape sequences * interpreted. */ - stringLiterals.put(litName, TokenUtils.descapeString(litVal)); + final String descVal = TokenUtils.descapeString(litVal); + stringLiterals.put(litName, descVal); + if(debugMode) + LOG.finer(String.format("Replaced string literal '%s' with literal no. %d", + descVal, nextLiteral)); nextLiteral += 1; - /* - * Place a ref. to the string in the command - */ + /* Place a ref. to the string in the command */ destringedCommand.append(" " + litName + " "); } else { destringedCommand.append(part); @@ -488,11 +411,11 @@ public class DiceLangEngine { } if (debugMode) { - System.out.println("\tCommand after destringing: " + destringedCommand); + String msg = String.format("\tCommand after destringing: %s\n", destringedCommand); + LOG.fine(msg); + System.out.print(msg); - /* - * Print the string table if it exists. - */ + /* Print the string table if it exists. */ if (stringLiterals.size() > 0) { System.out.println("\tString literals in table"); @@ -502,15 +425,11 @@ public class DiceLangEngine { } } - /* - * Split the command into tokens - */ + /* Split the command into tokens */ final String strang = destringedCommand.toString(); IList<String> tokens = FunctionalStringTokenizer.fromString(strang).toList(); - /* - * Temporarily remove non-expanding tokens - */ + /* Temporarily remove non-expanding tokens */ final IMap<String, String> nonExpandedTokens = new FunctionalMap<>(); tokens = tokens.map(tk -> { final Matcher nonExpandMatcher = nonExpandPattern.matcher(tk); @@ -519,6 +438,7 @@ public class DiceLangEngine { final String tkName = "nonExpandToken" + nextLiteral++; nonExpandedTokens.put(tkName, nonExpandMatcher.group(1)); + LOG.finer(String.format("Pulled non-expander '%s' to '%s'", nonExpandMatcher.group(1), tkName)); return tkName; } @@ -526,18 +446,20 @@ public class DiceLangEngine { }); if (debugMode) { - System.out.printf("\tCommand after removal of non-expanders: %s\n", tokens.toString()); + String msg = String.format("\tCommand after removal of non-expanders: %s\n", tokens.toString()); + LOG.fine(msg); + System.out.print(msg); } - /* - * Expand tokens - */ + /* Expand tokens */ IList<String> fullyExpandedTokens = tokens.flatMap(opExpander::split); - System.out.println("\tCommand after token expansion: " + fullyExpandedTokens.toString()); + if(debugMode) { + String msg = String.format("\tCommand after token expansion: %s\n", fullyExpandedTokens.toString()); + LOG.fine(msg); + System.out.print(msg); + } - /* - * Reinsert non-expanded tokens - */ + /* Reinsert non-expanded tokens */ fullyExpandedTokens = fullyExpandedTokens.map(tk -> { if (tk.startsWith("nonExpandToken")) return nonExpandedTokens.get(tk); @@ -545,18 +467,17 @@ public class DiceLangEngine { }); if (debugMode) { - System.out.printf("\tCommand after non-expander reinsertion: %s\n", - fullyExpandedTokens.toString()); + String msg = String.format("\tCommand after non-expander reinsertion: %s\n", + fullyExpandedTokens.toString()); + LOG.fine(msg); + System.out.print(msg); } return fullyExpandedTokens; } + /* Evaluate a forest of AST nodes. */ private void evaluateForest(final IList<ITree<Node>> astForest) { - if (debugMode) { - System.out.println("\tParsed forest of asts"); - } - int treeNo = 1; for (final ITree<Node> ast : astForest) { @@ -565,19 +486,16 @@ public class DiceLangEngine { } if (debugMode && stepEval) { + /* @TODO fix stepEval */ int step = 1; - /* - * Evaluate it step by step - */ + /* Evaluate it step by step */ for (final Iterator<ITree<Node>> itr = eval.stepDebug(ast); itr.hasNext();) { final ITree<Node> nodeStep = itr.next(); System.out.printf("\t\tStep %d: Node is %s", step, nodeStep); - /* - * Don't evaluate null steps - */ + /* Don't evaluate null steps */ if (nodeStep == null) { System.out.println(); @@ -585,9 +503,7 @@ public class DiceLangEngine { continue; } - /* - * Print out details for results - */ + /* Print out details for results */ if (nodeStep.getHead().type == Node.Type.RESULT) { final EvaluatorResult res = nodeStep.getHead().resultVal; @@ -611,9 +527,7 @@ public class DiceLangEngine { step += 1; } } else { - /* - * Evaluate it normally - */ + /* Evaluate it normally */ final EvaluatorResult res = eval.evaluate(ast); if (debugMode) { @@ -631,27 +545,19 @@ public class DiceLangEngine { } } - /* - * Preshunt preshunt-marked groups of tokens. - */ + /* Preshunt preshunt-marked groups of tokens. */ private boolean removePreshuntTokens(final IList<Token> lexedTokens, final IList<Token> preparedTokens) { - /* - * Current nesting level of tokens. - */ + /* Current nesting level of tokens. */ int curBraceCount = 0; - /* - * Data storage. - */ + /* Data storage. */ final Deque<IList<Token>> bracedTokens = new LinkedList<>(); IList<Token> curBracedTokens = new FunctionalList<>(); for (final Token tk : lexedTokens) { if (tk.type == Token.Type.OBRACE && tk.intValue == 2) { - /* - * Open a preshunt group. - */ + /* Open a preshunt group. */ curBraceCount += 1; if (curBraceCount != 1) { diff --git a/dice-lang/src/bjc/dicelang/Errors.java b/dice-lang/src/bjc/dicelang/Errors.java index 31d57b5..255db75 100644 --- a/dice-lang/src/bjc/dicelang/Errors.java +++ b/dice-lang/src/bjc/dicelang/Errors.java @@ -3,6 +3,10 @@ package bjc.dicelang; /** * Repository for error messages. * + * @TODO 10/08/17 Ben Culkin :ErrorRefactor + * This way of handling error messages is not easy to deal with. Something + * else needs to be done, but I'm not sure what at the moment. + * * @author EVE * */ @@ -14,7 +18,7 @@ public class Errors { * */ public static enum ErrorKey { - // Define Errors + /* Define Errors */ /** * Incorrect define guard syntax */ @@ -28,7 +32,7 @@ public class Errors { */ EK_DFN_RECUR, - // Console Errors + /* Console Errors */ /** * Unknown console pragma */ @@ -38,7 +42,7 @@ public class Errors { */ EK_CONS_INVDEFINE, - // Language Engine Errors + /* Language Engine Errors */ /** * Found closing double-brace w/out opening double-brace */ @@ -48,7 +52,7 @@ public class Errors { */ EK_ENG_NOCLOSING, - // Tokenizer Errors + /* Tokenizer Errors */ /** * Found an unexpected grouping token */ @@ -62,7 +66,7 @@ public class Errors { */ EK_TOK_INVFLEX, - // Evaluator Errors + /* Evaluator Errors */ /** * Unknown node type */ @@ -132,7 +136,7 @@ public class Errors { */ EK_EVAL_UNSTRING, - // Parser Error + /* Parser Error */ /** * Group closing where there couldn't be an opener */ @@ -154,7 +158,7 @@ public class Errors { */ EK_PARSE_INVTOKEN, - // Shunter Error + /* Shunter Error */ /** * Unary operator expected a operand, but got an operator */ @@ -180,7 +184,7 @@ public class Errors { */ EK_SHUNT_NOTASSOC, - // Stream Errors + /* Stream Errors */ /** * Attempted to switch to a non-existant stream */ @@ -194,7 +198,7 @@ public class Errors { */ EK_STRM_INVCOM, - // SCL Errors + /* SCL Errors */ /** * Unknown SCL token */ @@ -216,7 +220,7 @@ public class Errors { */ EK_SCL_INVARG, - // CLI Argument Errors + /* CLI Argument Errors */ /** * Unknown CLI argument */ @@ -230,7 +234,7 @@ public class Errors { */ EK_CLI_INVDFNTYPE, - // Miscellaneous errors + /* Miscellaneous errors */ /** * Unknown I/O problem */ @@ -239,6 +243,10 @@ public class Errors { * File not found */ EK_MISC_NOFILE, + + /* Dice errors. */ + /* Recieved the wrong sort of expression to a die. */ + EK_DICE_INVTYPE, } /** diff --git a/dice-lang/src/bjc/dicelang/Evaluator.java b/dice-lang/src/bjc/dicelang/Evaluator.java index b1a1ebd..d537ada 100644 --- a/dice-lang/src/bjc/dicelang/Evaluator.java +++ b/dice-lang/src/bjc/dicelang/Evaluator.java @@ -74,8 +74,8 @@ public class Evaluator { } private static Node FAIL(final EvaluatorResult res) { - return new Node(Node.Type.RESULT, new EvaluatorResult(FAILURE, new Node(Node.Type.RESULT, - res))); + EvaluatorResult eres = new EvaluatorResult(FAILURE, new Node(Node.Type.RESULT, res)); + return new Node(Node.Type.RESULT, eres); } private final DiceLangEngine eng; @@ -105,7 +105,7 @@ public class Evaluator { ctx.thunk = itr -> { /** * Deliberately finish the iterator, but ignore results. - * It's only for stepwise evaluation but we don't know + * It's only for stepwise evaluation, but we don't know * if stepping the iterator causes something to happen. * */ @@ -134,45 +134,41 @@ public class Evaluator { }, comm); } + /* Pick the way to evaluate a node. */ private TopDownTransformResult pickEvaluationType(final Node nd) { switch (nd.type) { case UNARYOP: switch (nd.operatorType) { case COERCE: return TopDownTransformResult.RTRANSFORM; - default: return TopDownTransformResult.PUSHDOWN; } - default: return TopDownTransformResult.PUSHDOWN; } } + /* Evaluate a node. */ private ITree<Node> evaluateNode(final ITree<Node> ast, final Context ctx) { switch (ast.getHead().type) { case UNARYOP: return evaluateUnaryOp(ast, ctx); - case BINOP: return evaluateBinaryOp(ast, ctx); - case TOKREF: return evaluateTokenRef(ast.getHead().tokenVal, ctx); - case ROOT: return ast.getChild(ast.getChildrenCount() - 1); - case RESULT: return ast; - default: Errors.inst.printError(EK_EVAL_INVNODE, ast.getHead().type.toString()); return new Tree<>(FAIL(ast)); } } + /* Evaluate a unary operator. */ private ITree<Node> evaluateUnaryOp(final ITree<Node> ast, final Context ctx) { if (ast.getChildrenCount() != 1) { Errors.inst.printError(EK_EVAL_UNUNARY, Integer.toString(ast.getChildrenCount())); @@ -180,9 +176,7 @@ public class Evaluator { } switch (ast.getHead().operatorType) { - /* - * TODO move coercing to its own class - */ + /* @TODO move coercing to its own class */ case COERCE: final ITree<Node> toCoerce = ast.getChild(0); final ITree<Node> retVal = new Tree<>(toCoerce.getHead()); diff --git a/dice-lang/src/bjc/dicelang/Tokenizer.java b/dice-lang/src/bjc/dicelang/Tokenizer.java index 259661d..8a366ac 100644 --- a/dice-lang/src/bjc/dicelang/Tokenizer.java +++ b/dice-lang/src/bjc/dicelang/Tokenizer.java @@ -3,33 +3,7 @@ package bjc.dicelang; import static bjc.dicelang.Errors.ErrorKey.EK_TOK_INVBASE; import static bjc.dicelang.Errors.ErrorKey.EK_TOK_INVFLEX; import static bjc.dicelang.Errors.ErrorKey.EK_TOK_UNGROUP; -import static bjc.dicelang.Token.Type.ADD; -import static bjc.dicelang.Token.Type.BIND; -import static bjc.dicelang.Token.Type.CBRACE; -import static bjc.dicelang.Token.Type.CBRACKET; -import static bjc.dicelang.Token.Type.COERCE; -import static bjc.dicelang.Token.Type.CPAREN; -import static bjc.dicelang.Token.Type.DICECONCAT; -import static bjc.dicelang.Token.Type.DICEFUDGE; -import static bjc.dicelang.Token.Type.DICEGROUP; -import static bjc.dicelang.Token.Type.DICELIST; -import static bjc.dicelang.Token.Type.DICESCALAR; -import static bjc.dicelang.Token.Type.DICE_LIT; -import static bjc.dicelang.Token.Type.DIVIDE; -import static bjc.dicelang.Token.Type.FLOAT_LIT; -import static bjc.dicelang.Token.Type.GROUPSEP; -import static bjc.dicelang.Token.Type.IDIVIDE; -import static bjc.dicelang.Token.Type.INT_LIT; -import static bjc.dicelang.Token.Type.LET; -import static bjc.dicelang.Token.Type.MULTIPLY; -import static bjc.dicelang.Token.Type.OBRACE; -import static bjc.dicelang.Token.Type.OBRACKET; -import static bjc.dicelang.Token.Type.OPAREN; -import static bjc.dicelang.Token.Type.STRCAT; -import static bjc.dicelang.Token.Type.STRING_LIT; -import static bjc.dicelang.Token.Type.STRREP; -import static bjc.dicelang.Token.Type.SUBTRACT; -import static bjc.dicelang.Token.Type.VREF; +import static bjc.dicelang.Token.Type.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -54,21 +28,21 @@ public class Tokenizer { litTokens = new FunctionalMap<>(); - litTokens.put("+", ADD); - litTokens.put("-", SUBTRACT); - litTokens.put("*", MULTIPLY); - litTokens.put("/", DIVIDE); - litTokens.put("//", IDIVIDE); - litTokens.put("sd", DICESCALAR); - litTokens.put("df", DICEFUDGE); - litTokens.put("dg", DICEGROUP); - litTokens.put("dc", DICECONCAT); - litTokens.put("dl", DICELIST); - litTokens.put("=>", LET); - litTokens.put(":=", BIND); + litTokens.put("+", ADD); + litTokens.put("-", SUBTRACT); + litTokens.put("*", MULTIPLY); + litTokens.put("/", DIVIDE); + litTokens.put("//", IDIVIDE); + litTokens.put("sd", DICESCALAR); + litTokens.put("df", DICEFUDGE); + litTokens.put("dg", DICEGROUP); + litTokens.put("dc", DICECONCAT); + litTokens.put("dl", DICELIST); + litTokens.put("=>", LET); + litTokens.put(":=", BIND); litTokens.put(".+.", STRCAT); litTokens.put(".*.", STRREP); - litTokens.put(",", GROUPSEP); + litTokens.put(",", GROUPSEP); litTokens.put("crc", COERCE); } @@ -89,7 +63,6 @@ public class Tokenizer { case '}': tk = tokenizeGrouping(token); break; - default: tk = tokenizeLiteral(token, stringLts); } @@ -106,27 +79,21 @@ public class Tokenizer { case '(': tk = new Token(OPAREN, token.length()); break; - case ')': tk = new Token(CPAREN, token.length()); break; - case '[': tk = new Token(OBRACKET, token.length()); break; - case ']': tk = new Token(CBRACKET, token.length()); break; - case '{': tk = new Token(OBRACE, token.length()); break; - case '}': tk = new Token(CBRACE, token.length()); break; - default: Errors.inst.printError(EK_TOK_UNGROUP, token); break; @@ -143,18 +110,17 @@ public class Tokenizer { private final Pattern stringLitMatcher = Pattern.compile("\\AstringLiteral(\\d+)\\Z"); - private Token tokenizeLiteral(final String token, final IMap<String, String> stringLts) { + private Token tokenizeLiteral(final String rtoken, final IMap<String, String> stringLts) { Token tk = Token.NIL_TOKEN; + String token = rtoken.trim(); if (TokenUtils.isInt(token)) { tk = new Token(INT_LIT, Long.parseLong(token)); } else if (hexadecimalMatcher.matcher(token).matches()) { final String newToken = token.substring(0, 1) + token.substring(token.indexOf('x')); - tk = new Token(INT_LIT, Long.parseLong(newToken.substring(2).toUpperCase(), 16)); } else if (flexadecimalMatcher.matcher(token).matches()) { final int parseBase = Integer.parseInt(token.substring(token.lastIndexOf('B') + 1)); - if (parseBase < Character.MIN_RADIX || parseBase > Character.MAX_RADIX) { Errors.inst.printError(EK_TOK_INVBASE, Integer.toString(parseBase)); return Token.NIL_TOKEN; @@ -181,15 +147,12 @@ public class Tokenizer { eng.addStringLiteral(litNum, stringLts.get(token)); tk = new Token(STRING_LIT, litNum); } else { - /* - * Everything else is a symbol - */ + /* Everything else is a symbol */ eng.symTable.put(nextSym++, token); tk = new Token(VREF, nextSym - 1); } } - return tk; } } diff --git a/dice-lang/src/bjc/dicelang/dice/CompoundDie.java b/dice-lang/src/bjc/dicelang/dice/CompoundDie.java index a81322c..0793872 100644 --- a/dice-lang/src/bjc/dicelang/dice/CompoundDie.java +++ b/dice-lang/src/bjc/dicelang/dice/CompoundDie.java @@ -6,11 +6,9 @@ package bjc.dicelang.dice; * @author Ben Culkin
*/
public class CompoundDie implements Die {
- /*
- * The dice that form this die
- */
- private final Die left;
- private final Die right;
+ /* The dice that form this die */
+ private final Die left;
+ private final Die right;
/**
* Create a new compound die.
@@ -32,24 +30,31 @@ public class CompoundDie implements Die { @Override
public long optimize() {
- return Long.parseLong(left.optimize() + "" + right.optimize());
+ long leftOpt = left.optimize();
+ long rightOpt = right.optimize();
+
+ return Long.parseLong(String.format("%d%d", leftOpt, rightOpt));
}
@Override
public long roll() {
- return Long.parseLong(left.roll() + "" + right.roll());
+ long leftRoll = left.optimize();
+ long rightRoll = right.optimize();
+
+ return Long.parseLong(String.format("%d%d", leftRoll, rightRoll));
}
@Override
public long rollSingle() {
- /*
- * We're only one die, we can't be split
- */
+ /* Actually one dice built using two, can't be split. */
return roll();
}
@Override
public String toString() {
- return left.toString() + "c" + right.toString();
+ String leftString = left.toString();
+ String rightString = right.toString();
+
+ return String.format("%sc%s", leftString, rightString);
}
}
diff --git a/dice-lang/src/bjc/dicelang/dice/CompoundingDie.java b/dice-lang/src/bjc/dicelang/dice/CompoundingDie.java index 1bd478f..4b3f137 100644 --- a/dice-lang/src/bjc/dicelang/dice/CompoundingDie.java +++ b/dice-lang/src/bjc/dicelang/dice/CompoundingDie.java @@ -11,9 +11,12 @@ import java.util.function.Predicate; * @author Ben Culkin
*/
public class CompoundingDie implements Die {
+ /* The source die to compound. */
private final Die source;
+ /* The predicate that marks when to compound. */
private final Predicate<Long> compoundOn;
+ /* The string version of the predicate, if one exists. */
private final String compoundPattern;
/**
@@ -48,22 +51,32 @@ public class CompoundingDie implements Die { @Override
public boolean canOptimize() {
- return source.canOptimize() && source.optimize() == 0;
+ if(source.canOptimize()) {
+ /* We can only be optimized for a result of zero. */
+ return source.optimize() == 0;
+ }
+
+ return false;
}
@Override
public long optimize() {
+ /* If we can be optimized, its to zero. */
return 0;
}
@Override
public long roll() {
+ /* The current result. */
long res = source.roll();
+ /* The last result. */
long oldRes = res;
while (compoundOn.test(oldRes)) {
+ /* Compound while the result should be compounded. */
oldRes = source.rollSingle();
+ /* Accumulate. */
res += oldRes;
}
@@ -72,15 +85,16 @@ public class CompoundingDie implements Die { @Override
public long rollSingle() {
- /*
- * Just compound on a single roll
- */
+ /* Just compound on an initial single role. */
long res = source.rollSingle();
+ /* The last result. */
long oldRes = res;
while (compoundOn.test(oldRes)) {
+ /* Compound while the result should be compounded. */
oldRes = source.rollSingle();
+ /* Accumulate. */
res += oldRes;
}
@@ -89,8 +103,13 @@ public class CompoundingDie implements Die { @Override
public String toString() {
- if (compoundPattern == null) return source + "!!";
+ String sourceString = source.toString();
+
+ /* Can't print a parseable version. */
+ if (compoundPattern == null) {
+ return String.format("%s!!<complex-pattern>", sourceString);
+ }
- return source + "!!" + compoundPattern;
+ return String.format("%s!!%s", sourceString, compoundPattern);
}
}
diff --git a/dice-lang/src/bjc/dicelang/dice/DiceBox.java b/dice-lang/src/bjc/dicelang/dice/DiceBox.java index afb2ea3..41b31af 100644 --- a/dice-lang/src/bjc/dicelang/dice/DiceBox.java +++ b/dice-lang/src/bjc/dicelang/dice/DiceBox.java @@ -21,110 +21,143 @@ public class DiceBox { * @return The die expression from the string, or null if it wasn't one */ public static DieExpression parseExpression(final String expString) { - /* - * Only bother with valid expressions. - */ - if (!isValidExpression(expString)) return null; + try { + return doParseExpression(expString); + } catch (Exception ex) { + /* + * @TODO 10/08/17 Ben Culkin :DieErrors :ErrorRefactor + * Use different types of exceptions to provide + * better error messages. */ + System.out.println("ERROR: Could not parse die expression (Cause: %s)\n", ex.getMessage); + ex.printStackTrace(); + + return null; + } + } + + private static DieExpression doParseExpression(final String expString) { + /* Only bother with valid expressions. */ + if (!isValidExpression(expString)) { + return null; + } if (scalarDiePattern.matcher(expString).matches()) { - /* - * Parse scalar die. + /* Parse scalar die. */ + /* @TODO 10/08/17 Ben Culkin :SubstringIndexOf + * This substring/index of call should be + * abstracted into its own method so as to make the + * code more explanatory and ensure that things + * like the return code of indexOf are correctly + * checked. */ final String dieString = expString.substring(0, expString.indexOf('s')); - final Die scal = new ScalarDie(Long.parseLong(dieString)); + + final long lar = Long.parseLong(dieString); + + final Die scal = new ScalarDie(lar); return new DieExpression(scal); } else if (simpleDiePattern.matcher(expString).matches()) { - /* - * Parse simple die groups. - */ + /* Parse simple die groups. */ final String[] dieParts = expString.split("d"); final long right = Long.parseLong(dieParts[1]); + final long left; if (dieParts[0].equals("")) { - /* - * Handle short-form expressions. - */ - final Die scal = new SimpleDie(1, right); - return new DieExpression(scal); + /* Handle short-form expressions. */ + left = 1; + } else { + left = Long.parseLong(dieParts[0]); } - final Die scal = new SimpleDie(Long.parseLong(dieParts[0]), right); + final Die scal = new SimpleDie(left, right); + return new DieExpression(scal); } else if (fudgeDiePattern.matcher(expString).matches()) { - /* - * Parse fudge dice. - */ + /* Parse fudge dice. */ + /* :SubstringIndexOf */ final String nDice = expString.substring(0, expString.indexOf('d')); + final Die fudge = new FudgeDie(Long.parseLong(nDice)); - return new DieExpression(new FudgeDie(Long.parseLong(nDice))); + return new DieExpression(fudge); } else if (compoundDiePattern.matcher(expString).matches()) { - /* - * Parse compound die expressions. - */ + /* Parse compound die expressions. */ final String[] dieParts = expString.split("c"); - final DieExpression left = parseExpression(dieParts[0]); + /* @TODO 10/08/17 :SplitParse + * Should this split string/parse split parts be + * abstracted into something else that handles + * doing the splitting correctly, as well as + * making sure that the resulting DieExpressions + * are of the right type? + */ + final DieExpression left = parseExpression(dieParts[0]); final DieExpression right = parseExpression(dieParts[1]); + /* :ErrorRefactor */ + if(left.isList) { + System.out.printf("ERROR: Expected a scalar die expression for lhs of compound die, got a list expression instead (%s)\n", left); + } else if(right.isList) { + System.out.printf("ERROR: Expected a scalar die expression for rhs of compound die, got a list expression instead (%s)\n", right); + } + + final Die compound = new CompoundDie(left.scalar, right.scalar); + return new DieExpression(new CompoundDie(left.scalar, right.scalar)); } else if (compoundingDiePattern.matcher(expString).matches()) { - /* - * Parse compounding die expressions. - */ + /* Parse compounding die expressions. */ final String[] dieParts = expString.split("!!"); - final DieExpression left = parseExpression(dieParts[0]); + final DieExpression left = parseExpression(dieParts[0]); final Predicate<Long> right = deriveCond(dieParts[1]); final Die scal = new CompoundingDie(left.scalar, right, dieParts[1]); + return new DieExpression(scal); } else if (explodingDiePattern.matcher(expString).matches()) { - /* - * Parse exploding die expressions. - */ + /* Parse exploding die expressions. */ final String[] dieParts = expString.split("!"); - final DieExpression left = parseExpression(dieParts[0]); + final DieExpression left = parseExpression(dieParts[0]); final Predicate<Long> right = deriveCond(dieParts[1]); final DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], false); + return new DieExpression(lst); } else if (penetratingDiePattern.matcher(expString).matches()) { - /* - * Parse penetrating die expressions. - */ + /* Parse penetrating die expressions. */ final String[] dieParts = expString.split("p!"); - final DieExpression left = parseExpression(dieParts[0]); + final DieExpression left = parseExpression(dieParts[0]); final Predicate<Long> right = deriveCond(dieParts[1]); final DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], true); + return new DieExpression(lst); } else if (diceListPattern.matcher(expString).matches()) { - /* - * Parse simple die lists. - */ + /* Parse simple die lists. */ final String[] dieParts = expString.split("dl"); - final DieExpression left = parseExpression(dieParts[0]); + final DieExpression left = parseExpression(dieParts[0]); final DieExpression right = parseExpression(dieParts[1]); final DieList lst = new SimpleDieList(left.scalar, right.scalar); return new DieExpression(lst); } + /* Unhandled type of die expression. */ + System.out.printf("INTERNAL ERROR: Valid die expression '%s' not parsed\n", expString); return null; } - /* - * The strings and patterns used for matching. - */ - - /* - * Defines a comparison predicate. + /* The strings and patterns used for matching. */ + /* @TODO 10/08/17 Ben Culkin :RegexResource + * These regexes and patterns should be moved to something + * external, probably using the SimpleProperties-based system that + * BJC-Utils2 uses. */ + /* Defines a comparison predicate. */ private static final String comparePoint = "[<>=]\\d+"; /* @@ -132,9 +165,9 @@ public class DiceBox { * * This is just a number. */ - private static final String scalarDie = "[\\+\\-]?\\d+sd"; - private static final Pattern scalarDiePattern = Pattern.compile("\\A" + - scalarDie + "\\Z"); + private static final String scalarDie = "[\\+\\-]?\\d+sd"; + private static final Pattern scalarDiePattern = Pattern.compile( + String.format("\\A%s\\Z", scalarDie)); /* * Defines a simple die. diff --git a/dice-lang/src/bjc/dicelang/expr/Ezpr.java b/dice-lang/src/bjc/dicelang/expr/Ezpr.java index bc1d5d4..77adc70 100644 --- a/dice-lang/src/bjc/dicelang/expr/Ezpr.java +++ b/dice-lang/src/bjc/dicelang/expr/Ezpr.java @@ -1,145 +1,145 @@ -package bjc.dicelang.expr; +// package bjc.dicelang.expr; -import bjc.utils.data.ITree; +// import bjc.utils.data.ITree; -import com.google.guava.collect.HashMultiset; -import com.google.guava.collect.Multiset; +// import com.google.guava.collect.HashMultiset; +// import com.google.guava.collect.Multiset; -import static bjc.dicelang.expr.EzprType; -import static bjc.dicelang.expr.EzprType.SUM; -import static bjc.dicelang.expr.EzprType.MUL; +// import static bjc.dicelang.expr.EzprType; +// import static bjc.dicelang.expr.EzprType.SUM; +// import static bjc.dicelang.expr.EzprType.MUL; -import static bjc.dicelang.expr.EzprNode; -import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType; -import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType.EZPR; -import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType.TOKEN; +// import static bjc.dicelang.expr.EzprNode; +// import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType; +// import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType.EZPR; +// import static bjc.dicelnag.ezpr.EzprNode.EzprNodeType.TOKEN; -public class Ezpr { - public static enum EzprType { - SUM, MUL - } +// public class Ezpr { +// public static enum EzprType { +// SUM, MUL +// } - public static class EzprNode { - public static enum EzprNodeType { - EZPR, TOKEN - } +// public static class EzprNode { +// public static enum EzprNodeType { +// EZPR, TOKEN +// } - public final EzprNodeType typ; +// public final EzprNodeType typ; - public final Ezpr ezp; - public final Token tok; +// public final Ezpr ezp; +// public final Token tok; - public EzprNode(Ezpr exp) { - typ = EZPR: +// public EzprNode(Ezpr exp) { +// typ = EZPR; - ezp = exp; - tok = null; - } +// ezp = exp; +// tok = null; +// } - public EzprNode(Token tk) { - typ = TOKEN; +// public EzprNode(Token tk) { +// typ = TOKEN; - tok = tk; - ezp = null; - } +// tok = tk; +// ezp = null; +// } - public String toString() { - if(typ == TOKEN) { - return tok.toString(); - } - return ezp.toString(); - } - } +// public String toString() { +// if(typ == TOKEN) { +// return tok.toString(); +// } +// return ezp.toString(); +// } +// } - private EzprType typ; +// private EzprType typ; - private Multiset<EzprNode> positive; - private Multiset<EzprNode> negative; +// private Multiset<EzprNode> positive; +// private Multiset<EzprNode> negative; - public Ezpr(EzprType type, Multiset<EzprNode> pos, Multiset<EzprNode> neg) { - typ = type; +// public Ezpr(EzprType type, Multiset<EzprNode> pos, Multiset<EzprNode> neg) { +// typ = type; - positive = pos; - negative = neg; - } - - public Ezpr flatten() { - HashMultiset<EzprNode> newPositive = HashMultiset<>.create(); - HashMultiset<EzprNode> newNegative = HashMultiset<>.create(); - - for(EzprNode nd : positive) { - /* Flatten enclosed ezprs of the same type. */ - if(nd.typ == EZPR && (nd.ezp.typ == typ)) { - /* Recursively flatten kids. */ - Ezpr kid = nd.ezp.flatten(); - - if(typ == SUM) { - /* Add sum parts to corresponding bags. */ - for(EzprNode knd : kid.positive) { - newPositive.add(knd); - } - for(EzprNode knd : kid.negative) { - newNegative.add(knd); - } - } else { - /* @TODO ensure that this is correct. */ - for(EzprNode knd : kid.positive) { - newPositive.add(knd); - } - for(EzprNode knd : kid.negative) { - newNegative.add(knd); - } - } - } else { - newPositive.add(nd); - } - } - - for(EzprNode nd : negative) { - /* Flatten enclosed ezprs of the same type. */ - if(nd.typ == EZPR && (nd.ezp.typ == typ)) { - /* Recursively flatten kids. */ - Ezpr kid = nd.ezp.flatten(); - - /* @TODO ensure that this is correct. */ - if(typ == SUM) { - for(EzprNode knd : kid.positive) { - newNegative.add(knd); - } - for(EzprNode knd : kid.negative) { - newPositive.add(knd); - } - } else { - for(EzprNode knd : kid.positive) { - newNegative.add(knd); - } - for(EzprNode knd : kid.negative) { - newPositive.add(knd); - } - } - } else { - newNegative.add(nd); - } - } - } - - public String toString() { - StringBuilder sb = new StringBuilder(typ.toString()); - - sb.append(" [ "); - for(EzprNode nd : positive) { - sb.append(nd.toString()); - sb.append(" "); - } - - sb.append("# "); - for(EzprNode nd : negative) { - sb.append(nd.toString()); - sb.append(" "); - } - - sb.append("]"); - - return sb.toString(); - } -} +// positive = pos; +// negative = neg; +// } + +// public Ezpr flatten() { +// HashMultiset<EzprNode> newPositive = HashMultiset.create(); +// HashMultiset<EzprNode> newNegative = HashMultiset.create(); + +// for(EzprNode nd : positive) { +// /* Flatten enclosed ezprs of the same type. */ +// if(nd.typ == EZPR && (nd.ezp.typ == typ)) { +// /* Recursively flatten kids. */ +// Ezpr kid = nd.ezp.flatten(); + +// if(typ == SUM) { +// /* Add sum parts to corresponding bags. */ +// for(EzprNode knd : kid.positive) { +// newPositive.add(knd); +// } +// for(EzprNode knd : kid.negative) { +// newNegative.add(knd); +// } +// } else { +// /* @TODO ensure that this is correct. */ +// for(EzprNode knd : kid.positive) { +// newPositive.add(knd); +// } +// for(EzprNode knd : kid.negative) { +// newNegative.add(knd); +// } +// } +// } else { +// newPositive.add(nd); +// } +// } + +// for(EzprNode nd : negative) { +// /* Flatten enclosed ezprs of the same type. */ +// if(nd.typ == EZPR && (nd.ezp.typ == typ)) { +// /* Recursively flatten kids. */ +// Ezpr kid = nd.ezp.flatten(); + +// /* @TODO ensure that this is correct. */ +// if(typ == SUM) { +// for(EzprNode knd : kid.positive) { +// newNegative.add(knd); +// } +// for(EzprNode knd : kid.negative) { +// newPositive.add(knd); +// } +// } else { +// for(EzprNode knd : kid.positive) { +// newNegative.add(knd); +// } +// for(EzprNode knd : kid.negative) { +// newPositive.add(knd); +// } +// } +// } else { +// newNegative.add(nd); +// } +// } +// } + +// public String toString() { +// StringBuilder sb = new StringBuilder(typ.toString()); + +// sb.append(" [ "); +// for(EzprNode nd : positive) { +// sb.append(nd.toString()); +// sb.append(" "); +// } + +// sb.append("# "); +// for(EzprNode nd : negative) { +// sb.append(nd.toString()); +// sb.append(" "); +// } + +// sb.append("]"); + +// return sb.toString(); +// } +// } diff --git a/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java b/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java index 71dacaa..4dc9b82 100644 --- a/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java +++ b/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java @@ -10,34 +10,32 @@ import java.util.function.Supplier; public class StreamControlConsole { public static void main(String[] args) { - /* - * We're not using the DiceLangEngine in the streams yet. - */ + /* Initialize vars. */ + /* We're not using the DiceLangEngine in the streams yet. */ StreamEngine sengine = new StreamEngine(null); - StreamControlEngine sclengine = new StreamControlEngine(sengine); - Scanner scn = new Scanner(System.in); + /* Get input from the user. */ System.out.print("Enter a SCL command string (blank to exit): "); - while(scn.hasNextLine()) { String ln = scn.nextLine(); - if(ln.trim().equals("")) break; + /* Break the token into strings. */ IList<String> res = new FunctionalList<>(); + String[] tokens = ln.split(" "); - String[] tokens = ln.split(" "); - + /* Run the stream engine on the tokens. */ boolean succ = sengine.doStreams(tokens, res); if(!succ) continue; + /* Run the command through SCL. */ tokens = res.toArray(new String[res.getSize()]); - - succ = sclengine.runProgram(tokens); + succ = sclengine.runProgram(tokens); if(!succ) continue; + /* Prompt again. */ System.out.print("Command string executed succesfully.\n\n"); System.out.print("Enter a SCL command string (blank to exit): "); } diff --git a/dice-lang/src/bjc/dicelang/scl/StreamEngine.java b/dice-lang/src/bjc/dicelang/scl/StreamEngine.java index 5094283..191ab41 100644 --- a/dice-lang/src/bjc/dicelang/scl/StreamEngine.java +++ b/dice-lang/src/bjc/dicelang/scl/StreamEngine.java @@ -27,30 +27,20 @@ import java.util.Arrays; * @author Ben Culkin */ public class StreamEngine { - /* - * Whether or not we're doing debugging. - */ + /* Whether or not we're doing debugging. */ public final boolean debug = true; - /* - * The engine we're attached to. - */ + /* The engine we're attached to. */ DiceLangEngine eng; - /* - * Our streams. - */ + /* Our streams. */ Tape<IList<String>> streams; IList<String> currStream; - /* - * Saved streams - */ + /* Saved streams */ TapeLibrary<IList<String>> savedStreams; - /* - * Handler for SCL programs - */ + /* Handler for SCL programs */ private final StreamControlEngine scleng; /** @@ -66,15 +56,12 @@ public class StreamEngine { scleng = new StreamControlEngine(this); } + /* Do pre-run (re)initialization. */ private void init() { - /* - * Reinitialize our list of streams. - */ + /* Reinitialize our list of streams. */ streams = new SingleTape<>(); - /* - * Create an initial stream. - */ + /* Create an initial stream. */ currStream = new FunctionalList<>(); streams.insertBefore(currStream); } @@ -94,28 +81,29 @@ public class StreamEngine { return doStreams(Arrays.asList(toks), dest); } + /** + * Process a possibly interleaved set of streams. + * + * @param toks + * The raw token to read streams from. + * + * @param dest + * The list to write the final stream to. + * + * @return Whether or not the streams were successfully processed. + */ public boolean doStreams(final Iterable<String> toks, final IList<String> dest) { - /* - * Initialize per-run state. - */ + /* Initialize per-run state. */ init(); - /* - * Are we currently quoting things? - */ + /* Are we currently quoting things? */ boolean quoteMode = false; - - /* - * Process each token. - */ + /* Process each token. */ for (final String tk : toks) { - /* - * Process stream commands. - */ + /* Process stream commands. */ if (tk.startsWith("{@S") && !quoteMode) { - if (tk.equals("{@SQ}")) { - quoteMode = true; - } else if (!processCommand(tk)) return false; + if (tk.equals("{@SQ}")) quoteMode = true; + else if (!processCommand(tk)) return false; } else { if (tk.equals("{@SU}")) { quoteMode = false; |
