summaryrefslogtreecommitdiff
path: root/dice-lang/src
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2017-10-08 16:38:35 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2017-10-08 16:38:35 -0300
commit054643900e7b857cafe123b0b4c03f10a95520ed (patch)
treec289fc397fe79ea0a6792e3f2f39a05ed1315936 /dice-lang/src
parentf40e5a873420d70d01ff7e01b77bdbd64faab00e (diff)
Update
Diffstat (limited to 'dice-lang/src')
-rw-r--r--dice-lang/src/bjc/dicelang/DiceLangConsole.java144
-rw-r--r--dice-lang/src/bjc/dicelang/DiceLangEngine.java308
-rw-r--r--dice-lang/src/bjc/dicelang/Errors.java30
-rw-r--r--dice-lang/src/bjc/dicelang/Evaluator.java20
-rw-r--r--dice-lang/src/bjc/dicelang/Tokenizer.java71
-rw-r--r--dice-lang/src/bjc/dicelang/dice/CompoundDie.java27
-rw-r--r--dice-lang/src/bjc/dicelang/dice/CompoundingDie.java31
-rw-r--r--dice-lang/src/bjc/dicelang/dice/DiceBox.java131
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Ezpr.java256
-rw-r--r--dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java20
-rw-r--r--dice-lang/src/bjc/dicelang/scl/StreamEngine.java62
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;