summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2017-10-25 12:10:14 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2017-10-25 12:10:14 -0300
commit7bda9de511a5642efb297eae98c6ea7c42b27754 (patch)
treedff1aa772b9ac088c5bd07b8d10d944cbff89f96 /dice-lang/src/bjc
parentf028ea6dc555fc5192a96b00b8e96e90dbf6de55 (diff)
Start switch to maven modules
Diffstat (limited to 'dice-lang/src/bjc')
-rw-r--r--dice-lang/src/bjc/dicelang/CLIArgsParser.java215
-rw-r--r--dice-lang/src/bjc/dicelang/CompilerTweaker.java102
-rw-r--r--dice-lang/src/bjc/dicelang/Define.java198
-rw-r--r--dice-lang/src/bjc/dicelang/DiceLangConsole.java320
-rw-r--r--dice-lang/src/bjc/dicelang/DiceLangEngine.java695
-rw-r--r--dice-lang/src/bjc/dicelang/Errors.java523
-rw-r--r--dice-lang/src/bjc/dicelang/Evaluator.java601
-rw-r--r--dice-lang/src/bjc/dicelang/EvaluatorResult.java220
-rw-r--r--dice-lang/src/bjc/dicelang/Node.java105
-rw-r--r--dice-lang/src/bjc/dicelang/Parser.java221
-rw-r--r--dice-lang/src/bjc/dicelang/Shunter.java380
-rw-r--r--dice-lang/src/bjc/dicelang/Token.java149
-rw-r--r--dice-lang/src/bjc/dicelang/Tokenizer.java174
-rw-r--r--dice-lang/src/bjc/dicelang/dice/CompoundDie.java60
-rw-r--r--dice-lang/src/bjc/dicelang/dice/CompoundingDie.java115
-rw-r--r--dice-lang/src/bjc/dicelang/dice/DiceBox.java310
-rw-r--r--dice-lang/src/bjc/dicelang/dice/Die.java39
-rw-r--r--dice-lang/src/bjc/dicelang/dice/DieExpression.java69
-rw-r--r--dice-lang/src/bjc/dicelang/dice/DieList.java31
-rw-r--r--dice-lang/src/bjc/dicelang/dice/ExplodingDice.java124
-rw-r--r--dice-lang/src/bjc/dicelang/dice/FudgeDie.java67
-rw-r--r--dice-lang/src/bjc/dicelang/dice/MathDie.java121
-rw-r--r--dice-lang/src/bjc/dicelang/dice/ScalarDie.java47
-rw-r--r--dice-lang/src/bjc/dicelang/dice/SimpleDie.java119
-rw-r--r--dice-lang/src/bjc/dicelang/dice/SimpleDieList.java77
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Ezpr.java149
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Lexer.java62
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Parser.java147
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Shunter.java110
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Token.java88
-rw-r--r--dice-lang/src/bjc/dicelang/expr/TokenType.java56
-rw-r--r--dice-lang/src/bjc/dicelang/expr/Tokens.java96
-rw-r--r--dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java75
-rw-r--r--dice-lang/src/bjc/dicelang/scl/StreamControlEngine.java546
-rw-r--r--dice-lang/src/bjc/dicelang/scl/StreamEngine.java266
-rw-r--r--dice-lang/src/bjc/dicelang/util/ResourceLoader.java43
36 files changed, 0 insertions, 6720 deletions
diff --git a/dice-lang/src/bjc/dicelang/CLIArgsParser.java b/dice-lang/src/bjc/dicelang/CLIArgsParser.java
deleted file mode 100644
index 54061bd..0000000
--- a/dice-lang/src/bjc/dicelang/CLIArgsParser.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package bjc.dicelang;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_CLI_INVDFNTYPE;
-import static bjc.dicelang.Errors.ErrorKey.EK_CLI_MISARG;
-import static bjc.dicelang.Errors.ErrorKey.EK_CLI_UNARG;
-import static bjc.dicelang.Errors.ErrorKey.EK_MISC_IOEX;
-import static bjc.dicelang.Errors.ErrorKey.EK_MISC_NOFILE;
-
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Scanner;
-
-import bjc.dicelang.util.ResourceLoader;
-
-/**
- * Parse CLI arguments.
- *
- * @author Ben Culkin
- *
- */
-public class CLIArgsParser {
- /**
- * Parse the provided set of CLI arguments.
- *
- * @param args
- * The CLI arguments to parse.
- * @param eng
- * The engine to affect with parsing.
- *
- * @return Whether or not to continue to the DiceLang repl.
- */
- public static boolean parseArgs(final String[] args, final DiceLangEngine eng) {
- if (args.length < 0) {
- return true;
- }
-
- if (args.length == 1 && (args[0].equals("--help") || args[0].equals("-h"))) {
- for (final String lne : ResourceLoader.loadHelpFile("cli")) {
- System.out.println(lne);
- }
-
- System.exit(0);
- }
-
- for (int i = 0; i < args.length; i++) {
- final String arg = args[i];
-
- /*
- * @TODO 10/08/17 Ben Culkin :CLIArgRefactor
- * Use whatever library gets added to BJC-Utils for
- * this, and extend these to do more things.
- */
- switch (arg) {
- case "-d":
- case "--debug":
- if (!eng.toggleDebug()) {
- eng.toggleDebug();
- }
- break;
- case "-nd":
- case "--no-debug":
- if (eng.toggleDebug()) {
- eng.toggleDebug();
- }
- break;
- case "-po":
- case "--postfix":
- if (!eng.togglePostfix()) {
- eng.togglePostfix();
- }
- break;
- case "-npo":
- case "--no-postfix":
- if (eng.togglePostfix()) {
- eng.togglePostfix();
- }
- break;
- case "-pr":
- case "--prefix":
- if (!eng.togglePrefix()) {
- eng.togglePrefix();
- }
- break;
- case "-npr":
- case "--no-prefix":
- if (eng.togglePrefix()) {
- eng.togglePrefix();
- }
- break;
- case "-se":
- case "--stepeval":
- if (!eng.toggleStepEval()) {
- eng.toggleStepEval();
- }
- break;
- case "-nse":
- case "--no-stepeval":
- if (eng.toggleStepEval()) {
- eng.toggleStepEval();
- }
- break;
- case "-D":
- case "--define":
- i = simpleDefine(i, args, eng);
- if (i == -1) {
- return false;
- }
- break;
- case "-df":
- case "--define-file":
- i = defineFile(i, args, eng);
- if (i == -1) {
- return false;
- }
- break;
- case "-ctf":
- case "--compiler-tweak-file":
- /* @NOTE
- * Not yet implemented.
- */
- default:
- Errors.inst.printError(EK_CLI_UNARG, arg);
- return false;
- }
- }
-
- return true;
- }
-
- /* Handle parsing a simple define. */
- private static int simpleDefine(final int i, final String[] args,
- final DiceLangEngine eng) {
- /* :DefineRefactor */
-
- if (i >= args.length - 1) {
- Errors.inst.printError(EK_CLI_MISARG, "define");
- return -1;
- }
-
- if (i >= args.length - 2) {
- final Define dfn = new Define(5, false, false, false, null, args[i + 1],
- Arrays.asList(""));
-
- if (dfn.inError) {
- return -1;
- }
-
- eng.addLineDefine(dfn);
- return i + 1;
- }
-
- final Define dfn = new Define(5, false, false, false, null, args[i + 1],
- Arrays.asList(args[i + 2]));
-
- if (dfn.inError) {
- return -1;
- }
-
- eng.addLineDefine(dfn);
- return i + 2;
- }
-
- /* Load a series of defines from a file. */
- private static int defineFile(final int i, final String[] args,
- final DiceLangEngine eng) {
- if (i >= args.length - 1) {
- Errors.inst.printError(EK_CLI_MISARG, "define-file");
- return -1;
- }
-
- final String fName = args[i + 1];
-
- try (FileInputStream fis = new FileInputStream(fName)) {
- try (Scanner scan = new Scanner(fis)) {
- while (scan.hasNextLine()) {
- final String ln = scan.nextLine();
-
- final Define dfn = parseDefine(ln.substring(ln.indexOf(' ')));
-
- if (dfn == null || dfn.inError) {
- return -1;
- }
-
- if (ln.startsWith("line")) {
- eng.addLineDefine(dfn);
- } else if (ln.startsWith("token")) {
- eng.addTokenDefine(dfn);
- } else {
- final String defnType = ln.substring(0, ln.indexOf(' '));
-
- Errors.inst.printError(EK_CLI_INVDFNTYPE, defnType);
- return -1;
- }
- }
- }
- } catch (final FileNotFoundException fnfex) {
- Errors.inst.printError(EK_MISC_NOFILE, fName);
- return -1;
- } catch (final IOException ioex) {
- Errors.inst.printError(EK_MISC_IOEX, fName);
- return -1;
- }
-
- return i + 1;
- }
-
- private static Define parseDefine(final String ln) {
- final Define res = null;
-
- /* :DefineRefactor */
- return res;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/CompilerTweaker.java b/dice-lang/src/bjc/dicelang/CompilerTweaker.java
deleted file mode 100644
index 1154be4..0000000
--- a/dice-lang/src/bjc/dicelang/CompilerTweaker.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package bjc.dicelang;
-
-import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter;
-
-/*
- * @TODO 10/09/17 Ben Culkin :CompilerTweaking
- * Expand this to allow tweaking more things about the compiler.
- */
-/**
- * Contains methods for customizing the DiceLang and SCL compilers.
- *
- * @author Ben Culkin
- */
-public class CompilerTweaker {
- /* Bits of the compiler necessary */
- private final DiceLangEngine eng;
- private final ConfigurableTokenSplitter opExpander;
-
- /**
- * Create a new compiler tweaker.
- *
- * @param engine
- * The engine to tweak.
- */
- public CompilerTweaker(final DiceLangEngine engine) {
- eng = engine;
-
- this.opExpander = engine.opExpander;
- }
-
- /**
- * Add a string literal to the compiler's internal banks.
- *
- * @param val
- * The string literal to add.
- *
- * @return The key into the string literal table for this string.
- */
- public int addStringLiteral(final String val) {
- eng.addStringLiteral(eng.nextLiteral, val);
-
- eng.nextLiteral += 1;
- return eng.nextLiteral;
- }
-
- /**
- * Add a line defn to the compiler.
- *
- * @param dfn
- * The defn to add.
- */
- public void addLineDefine(final Define dfn) {
- eng.addLineDefine(dfn);
- }
-
- /**
- * Add a token defn to the compiler.
- *
- * @param dfn
- * The defn to add.
- */
- public void addTokenDefine(final Define dfn) {
- eng.addTokenDefine(dfn);
- }
-
- /**
- * Adds delimiters that are expanded from tokens.
- *
- * @param delims
- * The delimiters to expand on.
- */
- public void addDelimiter(final String... delims) {
- opExpander.addSimpleDelimiters(delims);
- }
-
- /**
- * Adds multi-character delimiters that are expanded from tokens.
- *
- * @param delims
- * The multi-character delimiters to expand on.
- */
- public void addMultiDelimiter(final String... delims) {
- opExpander.addMultiDelimiters(delims);
- }
-
- /**
- * Make delimiter changes visible to the compiler.
- */
- public void compile() {
- opExpander.compile();
- }
-
- /**
- * Change the max no. of times defines are allowed to recur.
- *
- * @param times
- * The number of times to allow defines to recur.
- */
- public static void setDefineRecurLimit(final int times) {
- Define.MAX_RECURS = times;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Define.java b/dice-lang/src/bjc/dicelang/Define.java
deleted file mode 100644
index 5524477..0000000
--- a/dice-lang/src/bjc/dicelang/Define.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package bjc.dicelang;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_DFN_PREDSYN;
-import static bjc.dicelang.Errors.ErrorKey.EK_DFN_RECUR;
-import static bjc.dicelang.Errors.ErrorKey.EK_DFN_SRCSYN;
-
-import java.util.Iterator;
-import java.util.function.UnaryOperator;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import bjc.utils.data.CircularIterator;
-
-/*
- * @TODO 10/09/17 Ben Culkin :DefineRefactor
- * Consider replacing this with the defines package from BJC-Utils.
- */
-/**
- * A regular expression based pre-processor define.
- *
- * @author EVE
- *
- */
-public class Define implements UnaryOperator<String>, Comparable<Define> {
- /**
- * The define type.
- *
- * @author EVE
- *
- */
- public static enum Type {
- /** Match on lines. */
- LINE,
- /** Match on tokens. */
- TOKEN
- }
-
- /** The max amount of times to recur on expansions. */
- public static int MAX_RECURS = 10;
-
- /** The priority of this definition. */
- public final int priority;
-
- /** Whether or not this definition is in error. */
- public final boolean inError;
-
- /* Whether this define is recurring. */
- private boolean doRecur;
- /* Whether this define is applied multiple times per unit. */
- private boolean subType;
-
- /* The pattern that needs to match to apply this. */
- private Pattern predicate;
- /* The pattern to use to find everything to replace. */
- private Pattern searcher;
-
- /* The array of replacement strings to use. */
- private Iterator<String> replacers;
- /* The current replacement string to use. */
- private String replacer;
-
- /**
- * Create a new define.
- *
- * @param priorty
- * The priority of the define.
- *
- * @param isSub
- * Whether or not this is a 'sub-define'
- *
- * @param recur
- * Whether this define is recursive or not.
- *
- * @param isCircular
- * Whether this define is circular or not.
- *
- * @param predicte
- * The string to use as a predicate.
- *
- * @param searchr
- * The string to use as a search.
- *
- * @param replacrs
- * The source for replacement strings.
- */
- public Define(final int priorty, final boolean isSub, final boolean recur,
- final boolean isCircular,
- final String predicte, final String searchr, final Iterable<String> replacrs) {
- priority = priorty;
- doRecur = recur;
- subType = isSub;
-
- /* Only try to compile non-null predicates */
- if (predicte != null) {
- try {
- predicate = Pattern.compile(predicte);
- } catch (final PatternSyntaxException psex) {
- Errors.inst.printError(EK_DFN_PREDSYN, psex.getMessage());
- inError = true;
- return;
- }
- }
-
- /* Compile the search pattern */
- try {
- searcher = Pattern.compile(searchr);
- } catch (final PatternSyntaxException psex) {
- Errors.inst.printError(EK_DFN_SRCSYN, psex.getMessage());
- inError = true;
- return;
- }
-
- inError = false;
-
- /* Check whether or not we do sub-replacements */
- if (subType) {
- if (replacrs.iterator().hasNext()) {
- replacers = new CircularIterator<>(replacrs, isCircular);
- } else {
- replacers = null;
- }
- } else {
- final Iterator<String> itr = replacrs.iterator();
-
- if (itr.hasNext()) {
- replacer = itr.next();
- } else {
- replacer = "";
- }
- }
- }
-
- @Override
- public String apply(final String tok) {
- if (inError) {
- return tok;
- }
-
- if (predicate != null) {
- if (!predicate.matcher(tok).matches()) {
- return tok;
- }
- }
-
- String strang = doPass(tok);
-
- if (doRecur) {
- int recurCount = 0;
-
- if (strang.equals(tok)) {
- return strang;
- }
-
- final String oldStrang = strang;
-
- do {
- strang = doPass(tok);
- recurCount += 1;
- } while (!strang.equals(oldStrang) && recurCount < MAX_RECURS);
-
- if (recurCount >= MAX_RECURS) {
- Errors.inst.printError(EK_DFN_RECUR, Integer.toString(MAX_RECURS), tok, strang);
- return strang;
- }
- }
-
- return strang;
- }
-
- /* Apply a definition pass. */
- private String doPass(final String tok) {
- final Matcher searcherMatcher = searcher.matcher(tok);
-
- if (subType) {
- final StringBuffer sb = new StringBuffer();
-
- while (searcherMatcher.find()) {
- if (replacers == null) {
- searcherMatcher.appendReplacement(sb, "");
- } else {
- final String replac = replacers.next();
- searcherMatcher.appendReplacement(sb, replac);
- }
- }
-
- searcherMatcher.appendTail(sb);
- return sb.toString();
- }
-
- return searcherMatcher.replaceAll(replacer);
- }
-
- @Override
- public int compareTo(final Define o) {
- return priority - o.priority;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/DiceLangConsole.java b/dice-lang/src/bjc/dicelang/DiceLangConsole.java
deleted file mode 100644
index 296874f..0000000
--- a/dice-lang/src/bjc/dicelang/DiceLangConsole.java
+++ /dev/null
@@ -1,320 +0,0 @@
-package bjc.dicelang;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_CONS_INVDEFINE;
-import static bjc.dicelang.Errors.ErrorKey.EK_CONS_INVPRAG;
-
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import jline.ConsoleReader;
-import jline.Terminal;
-
-/**
- * CLI interface to DiceLang
- *
- * @author EVE
- *
- */
-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;
-
- /**
- * Create a new console.
- *
- * @param args
- * The CLI args for the console.
- */
- public DiceLangConsole(final String[] args) {
- commandNumber = 0;
- eng = new DiceLangEngine();
-
- if (!CLIArgsParser.parseArgs(args, eng)) {
- System.exit(1);
- }
-
- Terminal.setupTerminal();
- }
-
- /** Run the console. */
- public void run() {
- /* Set up console. */
- try {
- read = new ConsoleReader();
- } catch (final IOException ioex) {
- System.out.println("ERROR: Console init failed");
- return;
- }
-
- /* Print greeting. */
- System.out.println("dice-lang v0.2");
- String comm = null;
-
- /* Read initial command. */
- try {
- comm = read.readLine(String.format("(%d) dice-lang> ", commandNumber));
- } catch (final IOException ioex) {
- System.out.println("ERROR: I/O failed");
- return;
- }
-
- /* Run commands. */
- /* @NOTE
- * Should switch this to a do-while loop to reduce code
- * duplication.
- */
- while (!comm.equals("quit") && !comm.equals("exit")) {
- if (comm.startsWith("pragma")) {
- /* Run pragmas. */
- final boolean success = handlePragma(comm.substring(7));
-
- 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);
- }
-
- final boolean success = eng.runCommand(comm);
-
- if (success) {
- System.out.println("Command completed succesfully");
- } else {
- System.out.println("Command execution failed");
- }
-
- commandNumber += 1;
- }
-
- /* Read the next command. */
- try {
- comm = read.readLine(String.format("(%d) dice-lang> ", commandNumber));
- } catch (final IOException ioex) {
- System.out.println("ERROR: I/O failed");
- return;
- }
- }
- }
-
- /* Handle running pragmas. */
- private boolean handlePragma(final String pragma) {
- if (eng.debugMode) {
- System.out.println("\tRaw pragma: " + pragma);
- }
-
- /* 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);
- }
-
- /* Run pragmas. */
- /*
- * @TODO 10/09/17 Ben Culkin :PragmaRefactor
- * Swap to using something that makes it easier to add
- * pragmas.
- */
- switch (pragmaName) {
- 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;
- }
-
- return true;
- }
-
- /* Run a help mode. */
- private static boolean helpMode(final String pragma) {
- /* Get the help topic. */
- 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 */
- return true;
- }
-
- /* 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, or didn't get
- * something we need.
- */
- if (firstIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no priority)");
- return false;
- } else if (secondIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no define type)");
- return false;
- } else if (thirdIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no recursion type)");
- return false;
- } else if (fourthIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no guard type)");
- return false;
- } else if (fifthIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no circularity)");
- return false;
- } else if (sixthIndex == -1) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no patterns)");
- return false;
- }
-
- /* Get the priority and define type. */
- final int priority = Integer.parseInt(defineText.substring(0, firstIndex));
- final String defineType = defineText.substring(firstIndex + 1, secondIndex);
-
- Define.Type type;
- boolean subMode = false;
-
- /* Parse the define type. */
- switch (defineType) {
- 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;
- }
-
- /* Do we want this to be a recursive pattern? */
- final boolean doRecur = defineText.substring(secondIndex + 1, thirdIndex)
- .equalsIgnoreCase("true");
- /* Do we want this pattern to have a guard? */
- final boolean hasGuard = defineText.substring(thirdIndex + 1, fourthIndex)
- .equalsIgnoreCase("true");
- /* Do we want this pattern to use circular replacements. */
- final boolean isCircular = defineText.substring(thirdIndex + 1, fourthIndex)
- .equalsIgnoreCase("true");
-
- /* The part of the string that contains patterns. */
- final String pats = defineText.substring(fifthIndex + 1).trim();
- final Matcher patMatcher = slashPattern.matcher(pats);
- String guardPattern = null;
-
- if (hasGuard) {
- /* Grab the guard pattern. */
- if (!patMatcher.find()) {
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no guard pattern)");
- return false;
- }
-
- guardPattern = patMatcher.group(1);
- }
-
- if (!patMatcher.find()) {
- /* Grab the search pattern. */
- Errors.inst.printError(EK_CONS_INVDEFINE, "(no search pattern)");
- return false;
- }
-
- final String searchPattern = patMatcher.group(1);
- final List<String> replacePatterns = new LinkedList<>();
-
- while (patMatcher.find()) {
- /* Grab the replacer patterns. */
- replacePatterns.add(patMatcher.group(1));
- }
-
- final Define dfn = new Define(priority, subMode, doRecur,
- isCircular, guardPattern, searchPattern,
- replacePatterns);
-
- if (dfn.inError) {
- return false;
- }
-
- /* Add the define to the proper place. */
- if (type == Define.Type.LINE) {
- eng.addLineDefine(dfn);
- } else {
- eng.addTokenDefine(dfn);
- }
-
- return true;
- }
-
- /**
- * Main method.
- *
- * @param args
- * CLI arguments.
- */
- 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
deleted file mode 100644
index 71e5ee8..0000000
--- a/dice-lang/src/bjc/dicelang/DiceLangEngine.java
+++ /dev/null
@@ -1,695 +0,0 @@
-package bjc.dicelang;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_ENG_NOCLOSING;
-import static bjc.dicelang.Errors.ErrorKey.EK_ENG_NOOPENING;
-import static bjc.dicelang.Token.Type.CBRACE;
-import static bjc.dicelang.Token.Type.CBRACKET;
-import static bjc.dicelang.Token.Type.CPAREN;
-import static bjc.dicelang.Token.Type.OBRACE;
-import static bjc.dicelang.Token.Type.OBRACKET;
-import static bjc.dicelang.Token.Type.OPAREN;
-
-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;
-
-import bjc.dicelang.scl.StreamEngine;
-import bjc.utils.data.ITree;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.FunctionalMap;
-import bjc.utils.funcdata.FunctionalStringTokenizer;
-import bjc.utils.funcdata.IList;
-import bjc.utils.funcdata.IMap;
-import bjc.utils.funcutils.ListUtils;
-import bjc.utils.parserutils.TokenUtils;
-import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter;
-
-/**
- * Implements the orchestration necessary for processing DiceLang commands.
- *
- * @author Ben Culkin
- */
-public class DiceLangEngine {
- /* Logger. */
- private static final Logger LOG = Logger.getLogger(DiceLangEngine.class.getName());
-
- /*
- * The random fields that are package private instead of private-private
- * are for the benefit of the tweaker, so that it can mess around with
- * them.
- */
-
- /* Split tokens around operators with regex */
- ConfigurableTokenSplitter opExpander;
-
- /* ID for generation. */
- int nextLiteral;
-
- /* Debug indicator. */
- public boolean debugMode;
- /* Should we do shunting? */
- private boolean postfixMode;
- /* Should we reverse the token stream? */
- private boolean prefixMode;
- /* Should we do step-by-step evaluation? */
- private boolean stepEval;
-
- /* Shunter for token shunting. */
- Shunter shunt;
- /* Tokenizer for tokenizing. */
- Tokenizer tokenzer;
- /* Parser for tree construction. */
- Parser parsr;
- /* Evaluator for evaluating. */
- Evaluator eval;
-
- /* 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. */
- private final IList<Define> lineDefns;
- private final IList<Define> tokenDefns;
-
- /* Are defns currently sorted by priority? */
- private boolean defnsSorted;
-
- /* Stream engine for processing streams. */
- StreamEngine streamEng;
-
- /**
- * Create a new DiceLang engine.
- */
- public DiceLangEngine() {
- /* Initialize defns. */
- lineDefns = new FunctionalList<>();
- tokenDefns = new FunctionalList<>();
- defnsSorted = true;
-
- /* Initialize tables. */
- symTable = new FunctionalMap<>();
- stringLits = new FunctionalMap<>();
- stringLiterals = new FunctionalMap<>();
-
- /* Initialize operator expander. */
- opExpander = new ConfigurableTokenSplitter(true);
- opExpander.addMultiDelimiters("(", ")");
- opExpander.addMultiDelimiters("[", "]");
- opExpander.addMultiDelimiters("{", "}");
- opExpander.addSimpleDelimiters(":=");
- opExpander.addSimpleDelimiters("=>");
- opExpander.addSimpleDelimiters("//");
- opExpander.addSimpleDelimiters(".+.");
- opExpander.addSimpleDelimiters(".*.");
- opExpander.addSimpleDelimiters("+");
- opExpander.addSimpleDelimiters("-");
- opExpander.addSimpleDelimiters("*");
- opExpander.addSimpleDelimiters("/");
- opExpander.compile();
-
- /* Initialize literal IDs */
- nextLiteral = 1;
-
- /* Initial mode settings. */
- debugMode = true;
- postfixMode = false;
- prefixMode = false;
- stepEval = false;
-
- /* Create components. */
- shunt = new Shunter();
- parsr = new Parser();
-
- streamEng = new StreamEngine(this);
- tokenzer = new Tokenizer(this);
- eval = new Evaluator(this);
- }
-
- /** Sort defns by priority. */
- public void sortDefns() {
- lineDefns.sort(null);
- tokenDefns.sort(null);
-
- defnsSorted = true;
- }
-
- /**
- * Add a defn that's applied to lines.
- *
- * @param dfn
- * The defn to add.
- */
- public void addLineDefine(final Define dfn) {
- lineDefns.add(dfn);
-
- defnsSorted = false;
- }
-
- /**
- * Add a defn that's applied to tokens.
- *
- * @param dfn
- * The defn to add.
- */
- public void addTokenDefine(final Define dfn) {
- tokenDefns.add(dfn);
-
- defnsSorted = false;
- }
-
- /**
- * Toggle debug mode.
- *
- * @return The current state of debug mode.
- */
- public boolean toggleDebug() {
- debugMode = !debugMode;
-
- return debugMode;
- }
-
- /**
- * Toggle postfix mode.
- *
- * @return The current state of postfix mode.
- */
- public boolean togglePostfix() {
- postfixMode = !postfixMode;
-
- return postfixMode;
- }
-
- /**
- * Toggle prefix mode.
- *
- * @return The current state of prefix mode
- */
- public boolean togglePrefix() {
- prefixMode = !prefixMode;
-
- return prefixMode;
- }
-
- /**
- * Toggle step-eval mode
- *
- * @return The current state of step-eval mode
- */
- public boolean toggleStepEval() {
- stepEval = !stepEval;
-
- return stepEval;
- }
-
- /* Matches double-angle bracketed strings. */
- private final Pattern nonExpandPattern =
- Pattern.compile("<<([^\\>]*(?:\\>(?:[^\\>])*)*)>>");
-
- /**
- * Run a command to completion.
- *
- * @param command
- * The command to run
- *
- * @return Whether or not the command ran successfully
- */
- public boolean runCommand(final String command) {
- /* Preprocess the command into tokens */
- /* @NOTE
- * Instead of strings, this should maybe use a RawToken
- * class or something.
- */
- final IList<String> preprocessedTokens = preprocessCommand(command);
-
- if (preprocessedTokens == null) {
- return false;
- }
-
- /* 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 */
- final IList<ITree<Node>> astForest = new FunctionalList<>();
- final boolean succ = Parser.parseTokens(lexedTokens, astForest);
-
- if (!succ) {
- return false;
- }
-
- /* Evaluate the AST forest */
- evaluateForest(astForest);
- return true;
- }
-
- /* 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 */
- for (final Define dfn : tokenDefns.toIterable()) {
- /* @NOTE
- * What happens with a define that produces
- * multiple tokens from one token?
- */
- newTok = dfn.apply(newTok);
- }
-
- /* 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 */
- continue;
- } else if (tk == Token.NIL_TOKEN) {
- /* Fail on bad tokens */
- return null;
- } else {
- lexedTokens.add(tk);
- }
- }
-
- if (debugMode) {
- String msg = String.format("\tCommand after tokenization: %s\n", lexedTokens.toString());
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* 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) {
- String msg = String.format("\tCommand after pre-shunter removal: %s\n",
- preparedTokens.toString());
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* Only shunt if we're not in a special mode. */
- if (!postfixMode && !prefixMode) {
- /* Shunt the tokens */
- shuntedTokens = new FunctionalList<>();
- succ = shunt.shuntTokens(preparedTokens, shuntedTokens);
-
- if (!succ) {
- return null;
- }
- } else if (prefixMode) {
- /* Reverse directional tokens */
- /*
- * @NOTE
- * Merge these two operations into one iteration
- * over the list?
- */
- preparedTokens.reverse();
- shuntedTokens = preparedTokens.map(this::reverseToken);
- }
-
- if (debugMode && !postfixMode) {
- String msg = String.format("\tCommand after shunting: %s\n", shuntedTokens.toString());
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* Expand token groups */
- final IList<Token> readyTokens = shuntedTokens.flatMap(tk -> {
- 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);
- }
- });
-
- if (debugMode && !postfixMode) {
- String msg = String.format("\tCommand after re-preshunting: %s\n",
- readyTokens.toString());
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- return readyTokens;
- }
-
- /*
- * Reverse orientation-sensitive tokens.
- *
- * These are things like (, {, and [
- */
- private Token reverseToken(final Token tk) {
- 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. */
- private IList<String> preprocessCommand(final String command) {
- /* Sort the defines if they aren't sorted */
- if (!defnsSorted) {
- sortDefns();
- }
-
- /* 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;
- }
-
- String newComm = ListUtils.collapseTokens(streamToks, " ");
-
- if (debugMode) {
- String msg = String.format("\tCommand after stream commands: %s\n", newComm);
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* Apply line defns */
- for (final Define dfn : lineDefns.toIterable()) {
- newComm = dfn.apply(newComm);
- }
-
- if (debugMode) {
- String msg = String.format("\tCommand after line defines: %s\n", newComm);
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* Remove string literals. */
- final List<String> destringedParts = TokenUtils.removeDQuotedStrings(newComm);
- final StringBuffer destringedCommand = new StringBuffer();
-
- for (final String part : destringedParts) {
- /* Handle string literals */
- if (part.startsWith("\"") && part.endsWith("\"")) {
- /* Get the actual string. */
- final String litName = "stringLiteral" + nextLiteral;
- final String litVal = part.substring(1, part.length() - 1);
-
- /*
- * Insert the string with its escape sequences
- * interpreted.
- */
- 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 */
- destringedCommand.append(" " + litName + " ");
- } else {
- destringedCommand.append(part);
- }
- }
-
- if (debugMode) {
- String msg = String.format("\tCommand after destringing: %s\n", destringedCommand);
- LOG.fine(msg);
- System.out.print(msg);
-
- /* Print the string table if it exists. */
- if (stringLiterals.size() > 0) {
- System.out.println("\tString literals in table");
-
- stringLiterals.forEach((key, val) -> {
- System.out.printf("\t\tName: (%s)\tValue: (%s)\n", key, val);
- });
- }
- }
-
- /* Split the command into tokens */
- final String strang = destringedCommand.toString();
- IList<String> tokens = FunctionalStringTokenizer.fromString(strang).toList();
-
- /* Temporarily remove non-expanding tokens */
- final IMap<String, String> nonExpandedTokens = new FunctionalMap<>();
- tokens = tokens.map(tk -> {
- final Matcher nonExpandMatcher = nonExpandPattern.matcher(tk);
-
- if (nonExpandMatcher.matches()) {
- 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;
- }
-
- return tk;
- });
-
- if (debugMode) {
- String msg = String.format("\tCommand after removal of non-expanders: %s\n",
- tokens.toString());
- LOG.fine(msg);
- System.out.print(msg);
- }
-
- /* Expand tokens */
- IList<String> fullyExpandedTokens = tokens.flatMap(opExpander::split);
-
- 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 */
- fullyExpandedTokens = fullyExpandedTokens.map(tk -> {
- if (tk.startsWith("nonExpandToken")) return nonExpandedTokens.get(tk);
-
- return tk;
- });
-
- if (debugMode) {
- 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) {
- int treeNo = 1;
-
- for (final ITree<Node> ast : astForest) {
- if (debugMode) {
- System.out.printf("\t\tTree %d in forest:\n%s\n", treeNo, ast.toString());
- }
-
- if (debugMode && stepEval) {
- /*
- * @NOTE
- * This is broken until stepwise top-down
- * tree transforms are fixed.
- */
- int step = 1;
-
- /* 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 */
- if (nodeStep == null) {
- System.out.println();
-
- step += 1;
- continue;
- }
-
- /* Print out details for results */
- if (nodeStep.getHead().type == Node.Type.RESULT) {
- final EvaluatorResult res = nodeStep.getHead().resultVal;
-
- System.out.printf(" (result is %s", res);
-
- if (res.type == EvaluatorResult.Type.DICE) {
- System.out.printf(" (sample roll %s)", res.diceVal.value());
- }
-
- if (res.origVal != null) {
- System.out.printf(" (original tree is %s)", res.origVal);
- }
-
- System.out.printf(")");
- }
-
- /* Advance a step */
- System.out.println();
- step += 1;
- }
- } else {
- /* Evaluate it normally */
- final EvaluatorResult res = eval.evaluate(ast);
-
- if (debugMode) {
- System.out.printf("\t\tEvaluates to %s", res);
-
- if (res.type == EvaluatorResult.Type.DICE) {
- System.out.println("\t\t (sample roll " + res.diceVal.value() + ")");
- }
- }
- }
-
- System.out.println();
-
- treeNo += 1;
- }
- }
-
- /* Preshunt preshunt-marked groups of tokens. */
- private boolean removePreshuntTokens(final IList<Token> lexedTokens,
- final IList<Token> preparedTokens) {
- /* Current nesting level of tokens. */
- int curBraceCount = 0;
-
- /* 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. */
- curBraceCount += 1;
-
- if (curBraceCount != 1) {
- /*
- * Push the old group onto the group
- * stack.
- */
- bracedTokens.push(curBracedTokens);
- }
-
- curBracedTokens = new FunctionalList<>();
- } else if (tk.type == Token.Type.CBRACE && tk.intValue == 2) {
- /* Close a preshunt group. */
- if (curBraceCount == 0) {
- /*
- * Error if there couldn't have been an
- * opening.
- */
- Errors.inst.printError(EK_ENG_NOOPENING);
- return false;
- }
-
- curBraceCount -= 1;
-
- final IList<Token> preshuntTokens = new FunctionalList<>();
-
- /* Shunt preshunt group. */
- final boolean success = shunt.shuntTokens(curBracedTokens, preshuntTokens);
-
- if (debugMode) {
- System.out.println("\t\tPreshunted " + curBracedTokens + " into "
- + preshuntTokens);
- }
-
- if (!success) {
- return false;
- }
-
- if (curBraceCount >= 1) {
- /*
- * Add the preshunt group to the
- * previous group.
- */
- curBracedTokens = bracedTokens.pop();
-
- curBracedTokens.add(new Token(Token.Type.TOKGROUP, preshuntTokens));
- } else {
- /*
- * Add the preshunt group to the token
- * stream.
- */
- preparedTokens.add(new Token(Token.Type.TOKGROUP, preshuntTokens));
- }
- } else {
- /*
- * Add the token to the active preshunt group,
- * if there is one..
- */
- if (curBraceCount >= 1) {
- curBracedTokens.add(tk);
- } else {
- preparedTokens.add(tk);
- }
- }
- }
-
- if (curBraceCount > 0) {
- /* There was an unclosed group. */
- Errors.inst.printError(EK_ENG_NOCLOSING);
- return false;
- }
-
- return true;
- }
-
- /* Get a string literal from the string literal table. */
- String getStringLiteral(final int key) {
- return stringLits.get(key);
- }
-
- /* Add a string literal to the string literal table. */
- /* @NOTE
- * The string literal table should be abstracted into some kind of
- * auto-numbered map thing.
- */
- void addStringLiteral(final int key, final String val) {
- stringLits.put(key, val);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Errors.java b/dice-lang/src/bjc/dicelang/Errors.java
deleted file mode 100644
index 255db75..0000000
--- a/dice-lang/src/bjc/dicelang/Errors.java
+++ /dev/null
@@ -1,523 +0,0 @@
-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
- *
- */
-public class Errors {
- /**
- * The types of error message.
- *
- * @author EVE
- *
- */
- public static enum ErrorKey {
- /* Define Errors */
- /**
- * Incorrect define guard syntax
- */
- EK_DFN_PREDSYN,
- /**
- * Incorrect define search syntax
- */
- EK_DFN_SRCSYN,
- /**
- * Recursive define recursed too many times
- */
- EK_DFN_RECUR,
-
- /* Console Errors */
- /**
- * Unknown console pragma
- */
- EK_CONS_INVPRAG,
- /**
- * Improperly formatted define
- */
- EK_CONS_INVDEFINE,
-
- /* Language Engine Errors */
- /**
- * Found closing double-brace w/out opening double-brace
- */
- EK_ENG_NOOPENING,
- /**
- * Reached end of command w/out balanced double-braces
- */
- EK_ENG_NOCLOSING,
-
- /* Tokenizer Errors */
- /**
- * Found an unexpected grouping token
- */
- EK_TOK_UNGROUP,
- /**
- * Invalid base for a flexadecimal number
- */
- EK_TOK_INVBASE,
- /**
- * Invalid flexadecimal number in a given base
- */
- EK_TOK_INVFLEX,
-
- /* Evaluator Errors */
- /**
- * Unknown node type
- */
- EK_EVAL_INVNODE,
- /**
- * Incorrect # of args to binary operator
- */
- EK_EVAL_INVBIN,
- /**
- * Incorrect # of args to unary operator
- */
- EK_EVAL_INVUNARY,
- /**
- * Unknown binary operator
- */
- EK_EVAL_UNBIN,
- /**
- * Unknown unary operator
- */
- EK_EVAL_UNUNARY,
- /**
- * Math on strings doesn't work
- */
- EK_EVAL_STRINGMATH,
- /**
- * Attempted divide by zero
- */
- EK_EVAL_DIVZERO,
- /**
- * Attempted to divide dice
- */
- EK_EVAL_DIVDICE,
- /**
- * Unknown math operator
- */
- EK_EVAL_UNMATH,
- /**
- * Unknown token reference
- */
- EK_EVAL_UNTOK,
- /**
- * Unknown dice operator
- */
- EK_EVAL_UNDICE,
- /**
- * Incorrect type to dice group operator
- */
- EK_EVAL_INVDGROUP,
- /**
- * Incorrect type to dice creation operator
- */
- EK_EVAL_INVDCREATE,
- /**
- * Incorrect type to other dice operator
- */
- EK_EVAL_INVDICE,
- /**
- * Mismatched types to math operator
- */
- EK_EVAL_MISMATH,
- /**
- * Incorrect type to string operator
- */
- EK_EVAL_INVSTRING,
- /**
- * Unknown string operator
- */
- EK_EVAL_UNSTRING,
-
- /* Parser Error */
- /**
- * Group closing where there couldn't be an opener
- */
- EK_PARSE_NOCLOSE,
- /**
- * Group closing without group opener
- */
- EK_PARSE_UNCLOSE,
- /**
- * Incorrect # of arguments to binary operator
- */
- EK_PARSE_BINARY,
- /**
- * Not enough operands to binary operator
- */
- EK_PARSE_UNOPERAND,
- /**
- * Unrecognized token type
- */
- EK_PARSE_INVTOKEN,
-
- /* Shunter Error */
- /**
- * Unary operator expected a operand, but got an operator
- */
- EK_SHUNT_NOTADV,
- /**
- * Unary operator expected an operator, but got an operand
- */
- EK_SHUNT_NOTADJ,
- /**
- * Unary operator expected an operator, but didn't find one
- */
- EK_SHUNT_NOOP,
- /**
- * Asked for opening grouping operator, but couldn't find one
- */
- EK_SHUNT_NOGROUP,
- /**
- * No group for group seperator to attach to
- */
- EK_SHUNT_INVSEP,
- /**
- * Attempted to chain non-associative operator
- */
- EK_SHUNT_NOTASSOC,
-
- /* Stream Errors */
- /**
- * Attempted to switch to a non-existant stream
- */
- EK_STRM_NONEX,
- /**
- * Can't delete the last stream
- */
- EK_STRM_LAST,
- /**
- * Unknown stream command
- */
- EK_STRM_INVCOM,
-
- /* SCL Errors */
- /**
- * Unknown SCL token
- */
- EK_SCL_INVTOKEN,
- /**
- * Mismatched quote in SCL command
- */
- EK_SCL_MMQUOTE,
- /**
- * Stack underflow in SCL command
- */
- EK_SCL_SUNDERFLOW,
- /**
- * Unknown word in SCL command
- */
- EK_SCL_UNWORD,
- /**
- * Invalid argument to SCL command
- */
- EK_SCL_INVARG,
-
- /* CLI Argument Errors */
- /**
- * Unknown CLI argument
- */
- EK_CLI_UNARG,
- /**
- * Missing sub-argument to argument
- */
- EK_CLI_MISARG,
- /**
- * Invalid define type
- */
- EK_CLI_INVDFNTYPE,
-
- /* Miscellaneous errors */
- /**
- * Unknown I/O problem
- */
- EK_MISC_IOEX,
- /**
- * File not found
- */
- EK_MISC_NOFILE,
-
- /* Dice errors. */
- /* Recieved the wrong sort of expression to a die. */
- EK_DICE_INVTYPE,
- }
-
- /**
- * The mode for the type of error messages to print out.
- *
- * @author EVE
- *
- */
- public static enum ErrorMode {
- /**
- * Output error messages for wizards.
- */
- WIZARD,
- /**
- * Output error messages for developers.
- */
- DEV
- }
-
- private ErrorMode mode;
-
- /**
- * Print an error.
- *
- * @param key
- * The key of the error.
- *
- * @param args
- * The arguments for the error.
- */
- public void printError(final ErrorKey key, final String... args) {
- switch (mode) {
- case WIZARD:
- if (key == ErrorKey.EK_MISC_NOFILE) {
- System.out.println("\t? 404");
- } else {
- System.out.println("\t? " + key.ordinal());
- }
-
- break;
-
- case DEV:
- devError(key, args);
- break;
-
- default:
- System.out.println("\tERROR ERROR: Unknown error mode " + mode);
- }
- }
-
- private static void devError(final ErrorKey key, final String[] args) {
- switch (key) {
- case EK_DFN_PREDSYN:
- System.out.printf("\tERROR: Incorrect define guard syntax %s\n", args[0]);
- break;
-
- case EK_DFN_SRCSYN:
- System.out.printf("\tERROR: Incorrect define match syntax %s\n", args[0]);
- break;
-
- case EK_DFN_RECUR:
- System.out.printf(
- "\tERROR: Recursive define didn't converge after %s iterations."
- + " Original string was %s, last iteration was %s\n",
- args[0], args[1], args[2]);
- break;
-
- case EK_CONS_INVPRAG:
- System.out.printf("\tERROR: Unknown pragma %s\n", args[0]);
- break;
-
- case EK_CONS_INVDEFINE:
- System.out.printf("\tERROR: Improperly formatted define %s\n", args[0]);
- break;
-
- case EK_ENG_NOOPENING:
- System.out.printf("\tERROR: Encountered closing doublebrace without"
- + " matching opening doublebrace\n");
- break;
-
- case EK_ENG_NOCLOSING:
- System.out.printf("\tERROR: Reached end of string before closing doublebrace was found\n");
- break;
-
- case EK_TOK_UNGROUP:
- System.out.printf("\tERROR: Unrecognized grouping token %s\n", args[0]);
- break;
-
- case EK_TOK_INVBASE:
- System.out.printf("\tERROR: Invalid flexadecimal base %s\n", args[0]);
- break;
-
- case EK_TOK_INVFLEX:
- System.out.printf("\tERROR: Invalid flexadecimal number %s in base %s\n", args[0],
- args[1]);
- break;
-
- case EK_EVAL_INVNODE:
- System.out.printf("\tERROR: Unknown node in evaluator: %s\n", args[0]);
- break;
-
- case EK_EVAL_INVBIN:
- System.out.printf("\tERROR: Binary operators take 2 operands, not %s\n"
- + "\tProblem node is %s\n", args[0], args[1]);
- break;
-
- case EK_EVAL_UNBIN:
- System.out.printf("\tERROR: Unknown binary operator %s\n", args[0]);
- break;
-
- case EK_EVAL_STRINGMATH:
- System.out.printf("\tERROR: Math operators don't work on strings\n");
- break;
-
- case EK_EVAL_DIVZERO:
- System.out.printf("\tERROR: Attempted divide by zero\n");
- break;
-
- case EK_EVAL_DIVDICE:
- System.out.printf("\tERROR: Dice cannot be divided\n");
- break;
-
- case EK_EVAL_UNMATH:
- System.out.printf("\tERROR: Unknown math binary operator: %s\n", args[0]);
- break;
-
- case EK_EVAL_UNTOK:
- System.out.printf("\tERROR: Unknown token ref %s\n", args[0]);
- break;
-
- case EK_EVAL_UNDICE:
- System.out.printf("\tERROR: Unknown dice operator %s\n", args[0]);
- break;
-
- case EK_EVAL_INVDCREATE:
- System.out.printf("\tERROR: Dice creation operator expects integers," + " not %s\n",
- args[0]);
- break;
-
- case EK_EVAL_INVDGROUP:
- System.out.printf("\tERROR: Dice group operator expects scalar dice or integers," +
- " not %s\n",
- args[0]);
- break;
-
- case EK_EVAL_INVDICE:
- System.out.printf("\tERROR: Dice operators expect scalar dice, not %s\n", args[0]);
- break;
-
- case EK_EVAL_MISMATH:
- System.out.printf("\tERROR: Math operators expect two operands of the same type\n");
- break;
-
- case EK_EVAL_INVSTRING:
- System.out.printf("\tERROR: Incorrect type %s to string operator\n", args[0]);
- break;
-
- case EK_EVAL_UNSTRING:
- System.out.printf("\tERROR: Unknown string operator %s\n", args[0]);
- break;
-
- case EK_PARSE_NOCLOSE:
- System.out.printf("\tERROR: Group closing with no possible group opener\n");
- break;
-
- case EK_PARSE_UNCLOSE:
- System.out.printf("\tERROR: Found group closer without opener: (closing was %s"
- + ", expected %s)\n", args[0], args[1]);
- break;
-
- case EK_PARSE_BINARY:
- System.out.printf("\tERROR: Expected at least two operands\n");
- break;
-
- case EK_PARSE_UNOPERAND:
- System.out.printf("\tERROR: Operator %s expected more operands than provided\n", args[0]);
- break;
-
- case EK_PARSE_INVTOKEN:
- System.out.printf("\tERROR: Unrecognized token type in parsing: %s\n", args[0]);
- break;
-
- case EK_SHUNT_NOTADV:
- System.out.printf("\tERROR: Unary operator %s is an adjective, not an adverb. It can't be"
- + " applied to the operator %s\n", args[0], args[1]);
- break;
-
- case EK_SHUNT_NOTADJ:
- System.out.printf("\tERROR: Unary operator %s is an adjective, not an adverb. It can't be"
- + " applied to the operator %s\n", args[0], args[1]);
- break;
-
- case EK_SHUNT_NOOP:
- System.out.printf("\tERROR: Unary operator %s is an adverb, but there is no operator"
- + " to apply it to\n", args[0]);
- break;
-
- case EK_SHUNT_NOGROUP:
- System.out.printf("\tERROR: Couldn't find matching grouping %s (expected %s)\n", args[0],
- args[1]);
- break;
-
- case EK_SHUNT_NOTASSOC:
- System.out.printf("\tERROR: Attempted to chain non-associative operator %s\n", args[0]);
- break;
-
- case EK_SHUNT_INVSEP:
- System.out.printf("\tERROR: Couldn't find grouper for group seperator to attach to\n");
- break;
-
- case EK_STRM_NONEX:
- System.out.printf("\tERROR: Attempted to switch to non-existent stream\n");
- break;
-
- case EK_STRM_LAST:
- System.out.printf("\tERROR: Cannot delete last stream\n");
- break;
-
- case EK_STRM_INVCOM:
- System.out.printf("\tERROR: Unknown stream control command %s\n", args[0]);
- break;
-
- case EK_SCL_INVTOKEN:
- System.out.printf("\tERROR: Unknown SCL token %s\n", args[0]);
- break;
-
- case EK_SCL_MMQUOTE:
- System.out.printf("\tERROR: Mismatched delimiter in SCL command\n");
- break;
-
- case EK_SCL_SUNDERFLOW:
- System.out.printf("\tERROR: Not enough items in stack for word %s\n", args[0]);
- break;
-
- case EK_SCL_UNWORD:
- System.out.printf("\tERROR: Unknown word %s\n", args[0]);
- break;
-
- case EK_CLI_UNARG:
- System.out.printf("\tERROR: Unknown argument %s\n", args[0]);
- break;
-
- case EK_CLI_MISARG:
- System.out.printf("\tERROR: Missing subargument to command %s", args[0]);
- break;
-
- case EK_CLI_INVDFNTYPE:
- System.out.printf("\tERROR: Invalid define type %s\n", args[0]);
- break;
-
- case EK_MISC_IOEX:
- System.out.printf("\tERROR: I/O problem with file\n");
- break;
-
- case EK_MISC_NOFILE:
- System.out.printf("\tERROR: No such file %s\n", args[0]);
- break;
-
- default:
- System.out.printf("\tERROR ERROR: Unknown error key %s\n", key);
- }
- }
-
- /**
- * The instance of the errors.
- */
- public final static Errors inst;
-
- static {
- inst = new Errors();
-
- inst.mode = ErrorMode.DEV;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Evaluator.java b/dice-lang/src/bjc/dicelang/Evaluator.java
deleted file mode 100644
index 10f7651..0000000
--- a/dice-lang/src/bjc/dicelang/Evaluator.java
+++ /dev/null
@@ -1,601 +0,0 @@
-package bjc.dicelang;
-
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.function.Consumer;
-
-import bjc.dicelang.dice.CompoundDie;
-import bjc.dicelang.dice.FudgeDie;
-import bjc.dicelang.dice.MathDie;
-import bjc.dicelang.dice.ScalarDie;
-import bjc.dicelang.dice.SimpleDie;
-import bjc.dicelang.dice.SimpleDieList;
-import bjc.utils.data.ITree;
-import bjc.utils.data.SingleIterator;
-import bjc.utils.data.TopDownTransformIterator;
-import bjc.utils.data.TopDownTransformResult;
-import bjc.utils.data.Tree;
-
-import static bjc.dicelang.Errors.ErrorKey.*;
-import static bjc.dicelang.EvaluatorResult.Type.DICE;
-import static bjc.dicelang.EvaluatorResult.Type.FAILURE;
-import static bjc.dicelang.EvaluatorResult.Type.FLOAT;
-import static bjc.dicelang.EvaluatorResult.Type.INT;
-import static bjc.dicelang.EvaluatorResult.Type.STRING;
-
-
-/* @TODO 10/09/17 Ben Culkin :EvaluatorSplit
- * Type/sanity checking should be moved into a seperate stage, not part of
- * evaluation.
- */
-/**
- * Evaluate DiceLang ASTs
- *
- * @author EVE
- *
- */
-public class Evaluator {
- /* The steps of type coercion. */
- private static enum CoerceSteps {
- INTEGER, DOUBLE;
- }
-
- /* The context during iteration. */
- private static class Context {
- public Consumer<Iterator<ITree<Node>>> thunk;
-
- public boolean isDebug;
-
- public Context() {
- /* Empty block. */
- }
- }
-
- /* @TODO 10/09/17 Ben Culkin :NodeFAIL
- * These methods should be moved to Node.
- */
- /* Create a failing node. */
- private static Node FAIL() {
- return new Node(Node.Type.RESULT, new EvaluatorResult(FAILURE));
- }
-
- private static Node FAIL(final ITree<Node> orig) {
- return new Node(Node.Type.RESULT, new EvaluatorResult(FAILURE, orig));
- }
-
- private static Node FAIL(final Node orig) {
- return new Node(Node.Type.RESULT, new EvaluatorResult(FAILURE, orig));
- }
-
- private static Node FAIL(final EvaluatorResult res) {
- EvaluatorResult eres = new EvaluatorResult(FAILURE, new Node(Node.Type.RESULT, res));
- return new Node(Node.Type.RESULT, eres);
- }
-
- /* The engine we are connected to. */
- private final DiceLangEngine eng;
-
- /**
- * Create a new evaluator.
- *
- * @param en
- * The engine.
- */
- public Evaluator(final DiceLangEngine en) {
- eng = en;
- }
-
- /**
- * Evaluate a AST.
- *
- * @param comm
- * The AST to evaluate.
- *
- * @return The result of the tree.
- */
- public EvaluatorResult evaluate(final ITree<Node> comm) {
- final Context ctx = new Context();
-
- ctx.isDebug = false;
- ctx.thunk = itr -> {
- /*
- * Deliberately finish the iterator, but ignore results.
- * It's only for stepwise evaluation, but we don't know
- * if stepping the iterator has side effects.
- */
- while (itr.hasNext()) {
- itr.next();
- }
- };
-
- /* The result. */
- final ITree<Node> res = comm.topDownTransform(
- this::pickEvaluationType,
- node -> this.evaluateNode(node, ctx));
-
- return res.getHead().resultVal;
- }
-
- /* @NOTE
- * This is broken until stepwise top-down transforms are fixed. */
- public Iterator<ITree<Node>> stepDebug(final ITree<Node> comm) {
- final Context ctx = new Context();
-
- ctx.isDebug = true;
-
- return new TopDownTransformIterator<>(this::pickEvaluationType, (node, thnk) -> {
- ctx.thunk = thnk;
-
- return this.evaluateNode(node, ctx);
- }, comm);
- }
-
- /* Pick the way to evaluate a node. */
- private TopDownTransformResult pickEvaluationType(final Node nd) {
- switch (nd.type) {
- case UNARYOP:
- switch (nd.operatorType) {
- case COERCE:
- /* Coerce does special things to the tree. */
- 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) {
- /* Unary operators only take one operand. */
- if (ast.getChildrenCount() != 1) {
- Errors.inst.printError(EK_EVAL_UNUNARY, Integer.toString(ast.getChildrenCount()));
- return new Tree<>(FAIL(ast));
- }
-
- switch (ast.getHead().operatorType) {
- /*
- * @TODO 10/09/17 Ben Culkin :CoerceRefactor :EvaluatorSplit
- * Coercing should be moved to its own class, or at the
- * very least its own method. When the evaluator splits,
- * this node type'll be handled exclusively by the
- * type-checker.
- *
- * Coerce also needs to be able to coerce things to
- * dice and ratios (whenever they get added).
- */
- case COERCE:
- final ITree<Node> toCoerce = ast.getChild(0);
- final ITree<Node> retVal = new Tree<>(toCoerce.getHead());
- final Deque<ITree<Node>> children = new LinkedList<>();
-
- /* The current type we are coercing to. */
- CoerceSteps curLevel = CoerceSteps.INTEGER;
-
- for (int i = 0; i < toCoerce.getChildrenCount(); i++) {
- final ITree<Node> child = toCoerce.getChild(i);
- ITree<Node> nChild = null;
-
- /* Tell our thunk we processed a node. */
- if (ctx.isDebug) {
- /* Evaluate each step of the child. */
- final Iterator<ITree<Node>> nd = stepDebug(child);
-
- for (; nd.hasNext(); nChild = nd.next()) {
- ctx.thunk.accept(new SingleIterator<>(child));
- }
- } else {
- /* Evaluate the child. */
- nChild = new Tree<>(new Node(Node.Type.RESULT, evaluate(child)));
-
- ctx.thunk.accept(new SingleIterator<>(nChild));
- }
-
- if (nChild == null) {
- Errors.inst.printError(EK_EVAL_INVNODE);
- return new Tree<>(FAIL(ast));
- }
-
- final Node childNode = nChild.getHead();
- final EvaluatorResult res = childNode.resultVal;
-
- /* Move up to coercing to a float. */
- if (res.type == FLOAT) {
- curLevel = CoerceSteps.DOUBLE;
- }
-
- children.add(nChild);
- }
-
- for (final ITree<Node> child : children) {
- final Node nd = child.getHead();
- final EvaluatorResult res = nd.resultVal;
-
- switch (res.type) {
- case INT:
- /* Coerce ints to doubles if we need to. */
- if (curLevel == CoerceSteps.DOUBLE) {
- nd.resultVal = new EvaluatorResult(FLOAT, (double) res.intVal);
- }
- default:
- /* Do nothing */
- break;
- }
-
- retVal.addChild(child);
- }
-
- return retVal;
- case DICESCALAR:
- final EvaluatorResult opr = ast.getChild(0).getHead().resultVal;
-
- if (opr.type != INT) {
- Errors.inst.printError(EK_EVAL_INVDCREATE, opr.type.toString());
- }
-
- final EvaluatorResult sres = new EvaluatorResult(DICE, new ScalarDie(opr.intVal));
- return new Tree<>(new Node(Node.Type.RESULT, sres));
- case DICEFUDGE:
- final EvaluatorResult oprn = ast.getChild(0).getHead().resultVal;
-
- if (oprn.type != INT) {
- Errors.inst.printError(EK_EVAL_INVDCREATE, oprn.type.toString());
- }
-
- final EvaluatorResult fres = new EvaluatorResult(DICE, new ScalarDie(oprn.intVal));
- return new Tree<>(new Node(Node.Type.RESULT, fres));
- default:
- Errors.inst.printError(EK_EVAL_INVUNARY, ast.getHead().operatorType.toString());
- return new Tree<>(FAIL(ast));
- }
- }
-
- /* Evaluate a binary operator. */
- private static ITree<Node> evaluateBinaryOp(final ITree<Node> ast, final Context ctx) {
- final Token.Type binOp = ast.getHead().operatorType;
-
- /* Binary operators always have two children. */
- if (ast.getChildrenCount() != 2) {
- Errors.inst.printError(EK_EVAL_INVBIN, Integer.toString(ast.getChildrenCount()),
- ast.toString());
-
- return new Tree<>(FAIL(ast));
- }
-
- final ITree<Node> left = ast.getChild(0);
- final ITree<Node> right = ast.getChild(1);
-
- final EvaluatorResult leftRes = left.getHead().resultVal;
- final EvaluatorResult rightRes = right.getHead().resultVal;
-
- switch (binOp) {
- case ADD:
- case SUBTRACT:
- case MULTIPLY:
- case DIVIDE:
- case IDIVIDE:
- return evaluateMathBinary(binOp, leftRes, rightRes, ctx);
- case DICEGROUP:
- case DICECONCAT:
- case DICELIST:
- return evaluateDiceBinary(binOp, leftRes, rightRes, ctx);
- case STRCAT:
- case STRREP:
- return evaluateStringBinary(binOp, leftRes, rightRes, ctx);
- default:
- Errors.inst.printError(EK_EVAL_UNBIN, binOp.toString());
- return new Tree<>(FAIL(ast));
- }
- }
-
- /* Evaluate a binary operator on strings. */
- private static ITree<Node> evaluateStringBinary(final Token.Type op,
- final EvaluatorResult left,
- final EvaluatorResult right, final Context ctx) {
- if (left.type != STRING) {
- Errors.inst.printError(EK_EVAL_INVSTRING, left.type.toString());
- return new Tree<>(FAIL(left));
- }
-
- final String strang = left.stringVal;
-
- switch (op) {
- case STRCAT:
- if (right.type != STRING) {
- Errors.inst.printError(EK_EVAL_UNSTRING, right.type.toString());
- return new Tree<>(FAIL(right));
- }
-
- final String strung = right.stringVal;
- final EvaluatorResult cres = new EvaluatorResult(STRING, strang + strung);
-
- return new Tree<>(new Node(Node.Type.RESULT, cres));
- case STRREP:
- if (right.type != INT) {
- Errors.inst.printError(EK_EVAL_INVSTRING, right.type.toString());
- return new Tree<>(FAIL(right));
- }
-
- String res = strang;
- final long count = right.intVal;
-
- for (long i = 1; i < count; i++) {
- res += strang;
- }
-
- return new Tree<>(new Node(Node.Type.RESULT, new EvaluatorResult(STRING, res)));
- default:
- Errors.inst.printError(EK_EVAL_UNSTRING, op.toString());
- return new Tree<>(FAIL());
- }
- }
-
- /* Evaluate dice binary operators. */
- private static ITree<Node> evaluateDiceBinary(final Token.Type op,
- final EvaluatorResult left,
- final EvaluatorResult right, final Context ctx) {
- EvaluatorResult res = null;
-
- switch (op) {
- /*
- * @TODO 10/09/17 Ben Culkin :DiceSimplify
- * Figure out some way to simplify this sort of
- * thing.
- */
- case DICEGROUP:
- if (left.type == DICE && !left.diceVal.isList) {
- if (right.type == DICE && !right.diceVal.isList) {
- Die simple = new SimpleDie(
- left.diceVal.scalar,
- right.diceVal.scalar);
-
- res = new EvaluatorResult(DICE, simple);
- } else if (right.type == INT) {
- res = new EvaluatorResult(DICE,
- new SimpleDie(left.diceVal.scalar, right.intVal));
- } else {
- Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString());
- return new Tree<>(FAIL(right));
- }
- } else if (left.type == INT) {
- if (right.type == DICE && !right.diceVal.isList) {
- res = new EvaluatorResult(DICE,
- new SimpleDie(left.intVal, right.diceVal.scalar));
- } else if (right.type == INT) {
- res = new EvaluatorResult(DICE, new SimpleDie(left.intVal, right.intVal));
- } else {
- Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString());
- return new Tree<>(FAIL(right));
- }
- } else {
- Errors.inst.printError(EK_EVAL_INVDGROUP, left.type.toString());
- return new Tree<>(FAIL(left));
- }
-
- case DICECONCAT:
- if (left.type != DICE || left.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString());
- return new Tree<>(FAIL(left));
- } else if (right.type != DICE || right.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString());
- return new Tree<>(FAIL(right));
- } else {
- res = new EvaluatorResult(DICE,
- new CompoundDie(left.diceVal.scalar, right.diceVal.scalar));
- }
-
- break;
-
- case DICELIST:
- if (left.type != DICE || left.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString());
- return new Tree<>(FAIL(left));
- } else if (right.type != DICE || right.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString());
- return new Tree<>(FAIL(right));
- } else {
- res = new EvaluatorResult(DICE,
- new SimpleDieList(left.diceVal.scalar, right.diceVal.scalar));
- }
-
- break;
-
- default:
- Errors.inst.printError(EK_EVAL_UNDICE, op.toString());
- return new Tree<>(FAIL());
- }
-
- return new Tree<>(new Node(Node.Type.RESULT, res));
- }
-
- /* Evaluate a binary math operator. */
- private static ITree<Node> evaluateMathBinary(final Token.Type op,
- final EvaluatorResult left,
- final EvaluatorResult right, final Context ctx) {
- if (left.type == STRING || right.type == STRING) {
- Errors.inst.printError(EK_EVAL_STRINGMATH);
- return new Tree<>(FAIL());
- } else if (left.type == FAILURE || right.type == FAILURE) {
- return new Tree<>(FAIL());
- } else if (left.type == INT && right.type != INT) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(right));
- } else if (left.type == FLOAT && right.type != FLOAT) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(right));
- } else if (left.type == DICE && right.type != DICE) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(right));
- } else if (right.type == INT && left.type != INT) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(left));
- } else if (right.type == FLOAT && left.type != FLOAT) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(left));
- } else if (right.type == DICE && left.type != DICE) {
- Errors.inst.printError(EK_EVAL_MISMATH);
- return new Tree<>(FAIL(left));
- }
-
- EvaluatorResult res = null;
-
- switch (op) {
- case ADD:
- if (left.type == INT) {
- res = new EvaluatorResult(INT, left.intVal + right.intVal);
- } else if (left.type == DICE) {
- if (left.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
- return new Tree<>(FAIL(left));
- } else if (right.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, right.toString());
- return new Tree<>(FAIL(right));
- }
-
- res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.ADD, left.diceVal.scalar,
- right.diceVal.scalar));
- } else {
- res = new EvaluatorResult(FLOAT, left.floatVal + right.floatVal);
- }
-
- break;
-
- case SUBTRACT:
- if (left.type == INT) {
- res = new EvaluatorResult(INT, left.intVal - right.intVal);
- } else if (left.type == DICE) {
- if (left.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
- return new Tree<>(FAIL(left));
- } else if (right.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, right.toString());
- return new Tree<>(FAIL(right));
- }
-
- res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.SUBTRACT,
- left.diceVal.scalar, right.diceVal.scalar));
- } else {
- res = new EvaluatorResult(FLOAT, left.floatVal - right.floatVal);
- }
-
- break;
-
- case MULTIPLY:
- if (left.type == INT) {
- res = new EvaluatorResult(INT, left.intVal * right.intVal);
- } else if (left.type == DICE) {
- if (left.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, left.toString());
- return new Tree<>(FAIL(left));
- } else if (right.diceVal.isList) {
- Errors.inst.printError(EK_EVAL_INVDICE, right.toString());
- return new Tree<>(FAIL(right));
- }
-
- res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.MULTIPLY,
- left.diceVal.scalar, right.diceVal.scalar));
- } else {
- res = new EvaluatorResult(FLOAT, left.floatVal * right.floatVal);
- }
-
- break;
-
- case DIVIDE:
- if (left.type == INT) {
- if (right.intVal == 0) {
- Errors.inst.printError(EK_EVAL_DIVZERO);
- res = new EvaluatorResult(FAILURE, right);
- } else {
- res = new EvaluatorResult(FLOAT, left.intVal / right.intVal);
- }
- } else if (left.type == FLOAT) {
- if (right.floatVal == 0) {
- Errors.inst.printError(EK_EVAL_DIVZERO);
- res = new EvaluatorResult(FAILURE, right);
- } else {
- res = new EvaluatorResult(FLOAT, left.floatVal / right.floatVal);
- }
- } else {
- Errors.inst.printError(EK_EVAL_DIVDICE);
- return new Tree<>(FAIL());
- }
-
- break;
-
- case IDIVIDE:
- if (left.type == INT) {
- if (right.intVal == 0) {
- Errors.inst.printError(EK_EVAL_DIVZERO);
- res = new EvaluatorResult(FAILURE, right);
- } else {
- res = new EvaluatorResult(INT, (int) (left.intVal / right.intVal));
- }
- } else if (left.type == FLOAT) {
- if (right.floatVal == 0) {
- Errors.inst.printError(EK_EVAL_DIVZERO);
- res = new EvaluatorResult(FAILURE, right);
- } else {
- res = new EvaluatorResult(INT, (int) (left.floatVal / right.floatVal));
- }
- } else {
- Errors.inst.printError(EK_EVAL_DIVDICE);
- return new Tree<>(FAIL());
- }
-
- break;
-
- default:
- Errors.inst.printError(EK_EVAL_UNMATH, op.toString());
- return new Tree<>(FAIL());
- }
-
- return new Tree<>(new Node(Node.Type.RESULT, res));
- }
-
- /* Evaluate a token reference. */
- private ITree<Node> evaluateTokenRef(final Token tk, final Context ctx) {
- EvaluatorResult res = null;
-
- switch (tk.type) {
- case INT_LIT:
- res = new EvaluatorResult(INT, tk.intValue);
- break;
- case FLOAT_LIT:
- res = new EvaluatorResult(FLOAT, tk.floatValue);
- break;
- case DICE_LIT:
- res = new EvaluatorResult(DICE, tk.diceValue);
- break;
- case STRING_LIT:
- res = new EvaluatorResult(STRING, eng.getStringLiteral((int) tk.intValue));
- break;
- default:
- Errors.inst.printError(EK_EVAL_UNTOK, tk.type.toString());
- res = new EvaluatorResult(FAILURE);
- }
-
- return new Tree<>(new Node(Node.Type.RESULT, res));
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/EvaluatorResult.java b/dice-lang/src/bjc/dicelang/EvaluatorResult.java
deleted file mode 100644
index 3ceee9b..0000000
--- a/dice-lang/src/bjc/dicelang/EvaluatorResult.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package bjc.dicelang;
-
-import bjc.dicelang.dice.Die;
-import bjc.dicelang.dice.DieExpression;
-import bjc.dicelang.dice.DieList;
-import bjc.utils.data.ITree;
-import bjc.utils.data.Tree;
-
-/*
- * @TODO 10/09/17 Ben Culkin :EvalResultReorg
- * Again, split it into seperate classes based off of the type.
- */
-/**
- * The result from the evaluator.
- *
- * @author EVE
- *
- */
-public class EvaluatorResult {
- /**
- * The type of the result.
- *
- * @author EVE
- *
- */
- public static enum Type {
- /**
- * The type of a failure.
- */
- FAILURE,
- /**
- * The type of an integer.
- */
- INT,
- /**
- * The type of a float.
- */
- FLOAT,
- /**
- * The type of a dice.
- */
- DICE,
- /**
- * The type of a string.
- */
- STRING
- }
-
- /**
- * The type of the result.
- */
- public final EvaluatorResult.Type type;
-
- // These may or may not have values based
- // off of the result type
- /**
- * The integer value of the result.
- */
- public long intVal;
- /**
- * The float value of the result.
- */
- public double floatVal;
- /**
- * The dice value of the result.
- */
- public DieExpression diceVal;
- /**
- * The string value of the result.
- */
- public String stringVal;
-
- /**
- * Original node data
- */
- public ITree<Node> origVal;
-
- /**
- * Create a new result.
- *
- * @param typ
- * The type of the result.
- */
- public EvaluatorResult(final EvaluatorResult.Type typ) {
- type = typ;
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * The type of the result.
- *
- * @param orig
- * The original value of the result.
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final ITree<Node> orig) {
- this(typ);
-
- origVal = orig;
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * The type of the result.
- *
- * @param orig
- * The original value of the result.
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final Node orig) {
- this(typ, new Tree<>(orig));
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param orig
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final EvaluatorResult orig) {
- this(typ, new Node(Node.Type.RESULT, orig));
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param iVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final long iVal) {
- this(typ);
-
- intVal = iVal;
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param dVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final double dVal) {
- this(typ);
-
- floatVal = dVal;
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param dVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final DieExpression dVal) {
- this(typ);
-
- diceVal = dVal;
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param dVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final Die dVal) {
- this(typ);
-
- diceVal = new DieExpression(dVal);
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param dVal
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final DieList dVal) {
- this(typ);
-
- diceVal = new DieExpression(dVal);
- }
-
- /**
- * Create a new result.
- *
- * @param typ
- * @param strang
- */
- public EvaluatorResult(final EvaluatorResult.Type typ, final String strang) {
- this(typ);
-
- stringVal = strang;
- }
-
- @Override
- public String toString() {
- switch (type) {
- case INT:
- return type.toString() + "(" + intVal + ")";
-
- case FLOAT:
- return type.toString() + "(" + floatVal + ")";
-
- case DICE:
- return type.toString() + "(" + diceVal + ")";
-
- case STRING:
- return type.toString() + "(" + stringVal + ")";
-
- case FAILURE:
- return type.toString();
-
- default:
- return "Unknown result type " + type.toString();
- }
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Node.java b/dice-lang/src/bjc/dicelang/Node.java
deleted file mode 100644
index 4238cfc..0000000
--- a/dice-lang/src/bjc/dicelang/Node.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package bjc.dicelang;
-
-/*
- * @TODO 10/09/17 Ben Culkin :NodeReorg
- * Same thing, different class. Split into subclasses based off of the type
- * values.
- */
-/**
- * Represents a node in the AST.
- *
- * @author Ben Culkin
- */
-public class Node {
- public static enum Type {
- ROOT, TOKREF, UNARYOP, BINOP, GROUP, OGROUP, RESULT
- }
-
- public static enum GroupType {
- ARRAY, CODE
- }
-
- public final Type type;
-
- // These can have or not have values based of the node type
- public Token tokenVal;
- public Token.Type operatorType;
- public GroupType groupType;
- public EvaluatorResult resultVal;
-
- public Node(final Type typ) {
- type = typ;
- }
-
- public Node(final Type typ, final Token tokenVl) {
- this(typ);
-
- tokenVal = tokenVl;
- }
-
- public Node(final Type typ, final Token.Type opType) {
- this(typ);
-
- operatorType = opType;
- }
-
- public Node(final Type typ, final GroupType grupType) {
- this(typ);
-
- groupType = grupType;
- }
-
- public Node(final Type typ, final EvaluatorResult res) {
- this(typ);
-
- resultVal = res;
- }
-
- @Override
- public String toString() {
- switch (type) {
- case UNARYOP:
- case BINOP:
- return "(" + type.name() + " : " + operatorType + ")";
-
- case OGROUP:
- case TOKREF:
- return "(" + type.name() + " : " + tokenVal + ")";
-
- case GROUP:
- return "(" + type.name() + " : " + groupType + ")";
-
- case RESULT:
- return "(" + type.name() + " : " + resultVal + ")";
-
- default:
- return "Unknown node type " + type;
- }
- }
-
- @Override
- public boolean equals(final Object other) {
- if (!(other instanceof Node)) {
- return false;
- }
-
- final Node otk = (Node) other;
-
- if (otk.type != type) {
- return false;
- }
-
- switch (type) {
- case OGROUP:
- return tokenVal.equals(otk.tokenVal);
-
- default:
- return true;
- }
- }
-
- @Override
- public int hashCode() {
- return super.hashCode();
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Parser.java b/dice-lang/src/bjc/dicelang/Parser.java
deleted file mode 100644
index 0861e96..0000000
--- a/dice-lang/src/bjc/dicelang/Parser.java
+++ /dev/null
@@ -1,221 +0,0 @@
-package bjc.dicelang;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_PARSE_BINARY;
-import static bjc.dicelang.Errors.ErrorKey.EK_PARSE_INVTOKEN;
-import static bjc.dicelang.Errors.ErrorKey.EK_PARSE_NOCLOSE;
-import static bjc.dicelang.Errors.ErrorKey.EK_PARSE_UNCLOSE;
-import static bjc.dicelang.Errors.ErrorKey.EK_PARSE_UNOPERAND;
-import static bjc.dicelang.Node.Type.BINOP;
-import static bjc.dicelang.Node.Type.GROUP;
-import static bjc.dicelang.Node.Type.OGROUP;
-import static bjc.dicelang.Node.Type.TOKREF;
-import static bjc.dicelang.Node.Type.UNARYOP;
-import static bjc.dicelang.Token.Type.CBRACE;
-import static bjc.dicelang.Token.Type.CBRACKET;
-
-import java.util.Deque;
-import java.util.LinkedList;
-
-import bjc.utils.data.ITree;
-import bjc.utils.data.Tree;
-import bjc.utils.funcdata.IList;
-
-/**
- * Parse a series of tree into tokens.
- *
- * @author EVE
- *
- */
-public class Parser {
- /** Create a new parser. */
- public Parser() {
-
- }
-
- /**
- * Parse a series of tokens to a forest of ASTs.
- *
- * @param tokens
- * The list of tokens to parse.
- *
- * @param results
- * The place to set results.
- *
- * @return Whether or not the parse was successful.
- */
- public static boolean parseTokens(final IList<Token> tokens,
- final IList<ITree<Node>> results) {
- final Deque<ITree<Node>> working = new LinkedList<>();
-
- for (final Token tk : tokens) {
- switch (tk.type) {
- case OBRACKET:
- case OBRACE:
- /* Parse opening delims. */
- working.push(new Tree<>(new Node(OGROUP, tk)));
-
- break;
- case CBRACKET:
- case CBRACE:
- /* Parse closing delims. */
- final boolean sc = parseClosingGrouper(working, tk);
-
- if (!sc) {
- return false;
- }
-
- break;
- case MULTIPLY:
- case DIVIDE:
- case IDIVIDE:
- case DICEGROUP:
- case DICECONCAT:
- case DICELIST:
- case STRCAT:
- case STRREP:
- case LET:
- case BIND:
- /* Parse binary operator. */
- if (working.size() < 2) {
- Errors.inst.printError(EK_PARSE_BINARY);
- return false;
- }
-
- handleBinaryNode(working, tk);
- break;
- case ADD:
- case SUBTRACT:
- /* Handle binary/unary operators. */
- if (working.size() == 0) {
- Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString());
- return false;
- } else if (working.size() == 1) {
- final ITree<Node> operand = working.pop();
- final ITree<Node> opNode = new Tree<>(new Node(UNARYOP, tk.type));
-
- opNode.addChild(operand);
-
- working.push(opNode);
- } else {
- handleBinaryNode(working, tk);
- }
-
- break;
- case COERCE:
- case DICESCALAR:
- case DICEFUDGE:
- /* Handle unary operators. */
- if (working.size() == 0) {
- Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString());
- } else {
- final ITree<Node> operand = working.pop();
- final ITree<Node> opNode = new Tree<>(new Node(UNARYOP, tk.type));
-
- opNode.addChild(operand);
-
- working.push(opNode);
- }
-
- break;
- case INT_LIT:
- case FLOAT_LIT:
- case STRING_LIT:
- case VREF:
- case DICE_LIT:
- /* Handle literals. */
- working.push(new Tree<>(new Node(TOKREF, tk)));
- break;
- default:
- Errors.inst.printError(EK_PARSE_INVTOKEN, tk.type.toString());
- return false;
- }
- }
-
- /*
- * Collect the remaining nodes as the roots of the trees in the
- * AST forest.
- */
- for (final ITree<Node> ast : working) {
- results.add(ast);
- }
-
- return true;
- }
-
- /* Handle a binary operator. */
- private static void handleBinaryNode(final Deque<ITree<Node>> working, final Token tk) {
- final ITree<Node> right = working.pop();
- final ITree<Node> left = working.pop();
-
- final ITree<Node> opNode = new Tree<>(new Node(BINOP, tk.type));
-
- opNode.addChild(left);
- opNode.addChild(right);
-
- working.push(opNode);
- }
-
- /* Parse a closing delimiter. */
- private static boolean parseClosingGrouper(final Deque<ITree<Node>> working,
- final Token tk) {
- if (working.size() == 0) {
- Errors.inst.printError(EK_PARSE_NOCLOSE);
- return false;
- }
-
- ITree<Node> groupNode = null;
-
- switch (tk.type) {
- case CBRACE:
- groupNode = new Tree<>(new Node(GROUP, Node.GroupType.CODE));
- break;
- case CBRACKET:
- groupNode = new Tree<>(new Node(GROUP, Node.GroupType.ARRAY));
- break;
- default:
- Errors.inst.printError(EK_PARSE_UNCLOSE, tk.type.toString());
- return false;
- }
-
- Token matching = null;
-
- if (tk.type == CBRACKET) {
- matching = new Token(Token.Type.OBRACKET, tk.intValue);
- } else if (tk.type == CBRACE) {
- matching = new Token(Token.Type.OBRACE, tk.intValue);
- }
-
- final ITree<Node> matchNode = new Tree<>(new Node(OGROUP, matching));
-
- if (!working.contains(matchNode)) {
- Errors.inst.printError(EK_PARSE_UNCLOSE, tk.toString(), matchNode.toString());
-
- System.out.println("\tCurrent forest is: ");
-
- int treeNo = 1;
-
- for (final ITree<Node> ast : working) {
- System.out.println("Tree " + treeNo++ + ": " + ast.toString());
- }
-
- return false;
- }
-
- final Deque<ITree<Node>> childs = new LinkedList<>();
-
- while (!working.peek().equals(matchNode)) {
- childs.push(working.pop());
- }
-
- /* Discard opener */
- working.pop();
-
- for (final ITree<Node> child : childs) {
- groupNode.addChild(child);
- }
-
- working.push(groupNode);
-
- return true;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Shunter.java b/dice-lang/src/bjc/dicelang/Shunter.java
deleted file mode 100644
index 9d63b41..0000000
--- a/dice-lang/src/bjc/dicelang/Shunter.java
+++ /dev/null
@@ -1,380 +0,0 @@
-package bjc.dicelang;
-
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.FunctionalMap;
-import bjc.utils.funcdata.IList;
-import bjc.utils.funcdata.IMap;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_SHUNT_INVSEP;
-import static bjc.dicelang.Errors.ErrorKey.EK_SHUNT_NOGROUP;
-import static bjc.dicelang.Errors.ErrorKey.EK_SHUNT_NOTADJ;
-import static bjc.dicelang.Errors.ErrorKey.EK_SHUNT_NOTADV;
-import static bjc.dicelang.Errors.ErrorKey.EK_SHUNT_NOTASSOC;
-import static bjc.dicelang.Token.Type.*;
-
-/**
- * Shunt a set of infix tokens to postfix tokens.
- *
- * @author EVE
- *
- */
-public class Shunter {
- /* The binary operators and their priorities. */
- IMap<Token.Type, Integer> ops;
-
- /* Operators that are right-associative */
- Set<Token.Type> rightAssoc;
-
- /* Operators that aren't associative */
- Set<Token.Type> notAssoc;
-
- /*
- * Unary operators that can only be applied to non-operator tokens and
- * yield operator tokens.
- */
- Set<Token.Type> unaryAdjectives;
-
- /*
- * Unary operators that can only be applied to operator tokens and yield
- * operator tokens.
- */
- Set<Token.Type> unaryAdverbs;
-
- /*
- * Unary operators that can only be applied to operator tokens and yield
- * data tokens
- */
- Set<Token.Type> unaryGerunds;
-
- /** Precedence for math operators. */
- public final int MATH_PREC = 30;
- /** Precedence for dice operators. */
- public final int DICE_PREC = 20;
- /** Precedence for string operators. */
- public final int STR_PREC = 10;
- /** Precedence for expression operators. */
- public final int EXPR_PREC = 0;
-
- /** Create a new shunter. */
- public Shunter() {
- /* Create op map. */
- ops = new FunctionalMap<>();
-
- /* Create association maps. */
- rightAssoc = new HashSet<>();
- notAssoc = new HashSet<>();
-
- /* Create unary maps. */
- unaryAdjectives = new HashSet<>();
- unaryAdverbs = new HashSet<>();
- unaryGerunds = new HashSet<>();
-
- /* Set up unary adverbs. */
- unaryAdverbs.add(COERCE);
-
- /* Setup operators. */
- /* Math operators. */
- ops.put(ADD, 0 + MATH_PREC);
- ops.put(SUBTRACT, 0 + MATH_PREC);
-
- ops.put(MULTIPLY, 1 + MATH_PREC);
- ops.put(IDIVIDE, 1 + MATH_PREC);
- ops.put(DIVIDE, 1 + MATH_PREC);
-
- /* Dice operators. */
- ops.put(DICEGROUP, 0 + DICE_PREC);
-
- ops.put(DICECONCAT, 1 + DICE_PREC);
-
- ops.put(DICELIST, 2 + DICE_PREC);
-
- /* String operators. */
- ops.put(STRCAT, 0 + STR_PREC);
-
- ops.put(STRREP, 1 + STR_PREC);
-
- /* Expression operators. */
- ops.put(LET, 0 + EXPR_PREC);
-
- ops.put(BIND, 1 + EXPR_PREC);
- }
-
- /**
- * Shunt a set of tokens from infix to postfix.
- *
- * @param tks
- * The tokens to input.
- *
- * @param returned
- * The postfix tokens.
- *
- * @return Whether or not the shunt succeeded.
- */
- public boolean shuntTokens(final IList<Token> tks, final IList<Token> returned) {
- /* Operator stack for normal and unary operators. */
- final Deque<Token> opStack = new LinkedList<>();
- final Deque<Token> unaryOps = new LinkedList<>();
-
- /* Currently returned lists. */
- final Deque<Token> currReturned = new LinkedList<>();
-
- /* Tokens to feed ahead of the current one. */
- final Deque<Token> feed = new LinkedList<>();
-
- for (final Token tk : tks.toIterable()) {
- boolean succ;
-
- /* Drain the feed queue. */
- while (feed.size() != 0) {
- succ = shuntToken(feed.poll(), opStack, unaryOps, currReturned, feed);
-
- if (!succ) {
- return false;
- }
- }
-
- succ = shuntToken(tk, opStack, unaryOps, currReturned, feed);
-
- if (!succ) {
- return false;
- }
- }
-
- /* Flush leftover operators. */
- while (!opStack.isEmpty()) {
- currReturned.addLast(opStack.pop());
- }
-
- /* Add the tokens to the returned list. */
- for (final Token tk : currReturned) {
- returned.add(tk);
- }
-
- return true;
- }
-
- /* Shunt a token. */
- private boolean shuntToken(final Token tk, final Deque<Token> opStack,
- final Deque<Token> unaryStack,
- final Deque<Token> currReturned, final Deque<Token> feed) {
- /* Handle unary operators. */
- if (unaryStack.size() != 0) {
- if (isUnary(tk)) {
- unaryStack.add(tk);
- return true;
- }
-
- final Token unaryOp = unaryStack.pop();
-
- final Token.Type unaryType = unaryOp.type;
-
- if (unaryAdjectives.contains(unaryType)) {
- /*
- * Handle unary adjectives that take a
- * non-operator.
- */
- if (isOp(tk)) {
- Errors.inst.printError(EK_SHUNT_NOTADV, unaryOp.toString(), tk.toString());
- return false;
- }
-
- final Token newTok = new Token(TAGOPR);
-
- if (tk.type == TAGOP) {
- newTok.tokenValues = tk.tokenValues;
- } else {
- newTok.tokenValues = new FunctionalList<>(tk);
- }
-
- newTok.tokenValues.add(unaryOp);
- opStack.push(newTok);
-
- return true;
- } else if (unaryAdverbs.contains(unaryType)) {
- /* Handle unary adverbs that take an operator. */
- if (!isOp(tk)) {
- Errors.inst.printError(EK_SHUNT_NOTADJ, unaryOp.toString(), tk.toString());
- return false;
- }
-
- final Token newTok = new Token(TAGOPR);
-
- if (tk.type == TAGOP) {
- newTok.tokenValues = tk.tokenValues;
- } else {
- newTok.tokenValues = new FunctionalList<>(tk);
- }
-
- newTok.tokenValues.add(unaryOp);
- opStack.push(newTok);
-
- return true;
- }
- }
-
- if (isUnary(tk)) {
- unaryStack.add(tk);
- return true;
- } else if (isOp(tk)) {
- /* Drain higher precedence operators. */
- while (!opStack.isEmpty() && isHigherPrec(tk, opStack.peek())) {
- final Token newOp = opStack.pop();
-
- if (tk.type == newOp.type && notAssoc.contains(tk.type)) {
- Errors.inst.printError(EK_SHUNT_NOTASSOC, tk.type.toString());
- }
-
- currReturned.addLast(newOp);
- }
-
- opStack.push(tk);
- } else if (tk.type == OPAREN || tk.type == OBRACE) {
- opStack.push(tk);
-
- if (tk.type == OBRACE) {
- currReturned.addLast(tk);
- }
- } else if (tk.type == CPAREN || tk.type == CBRACE) {
- /* Handle closing delimiter. */
- Token matching = null;
-
- switch (tk.type) {
- case CPAREN:
- matching = new Token(OPAREN, tk.intValue);
- break;
- case CBRACE:
- matching = new Token(OBRACE, tk.intValue);
- break;
- default:
- Errors.inst.printError(EK_SHUNT_NOGROUP);
- return false;
- }
-
- if (!opStack.contains(matching)) {
- Errors.inst.printError(EK_SHUNT_NOGROUP, tk.toString(), matching.toString());
- return false;
- }
-
- while (!opStack.peek().equals(matching)) {
- currReturned.addLast(opStack.pop());
- }
-
- if (tk.type == CBRACE) {
- currReturned.addLast(tk);
- }
-
- opStack.pop();
- } else if (tk.type == GROUPSEP) {
- /* Add a grouped token. */
- final IList<Token> group = new FunctionalList<>();
-
- while (currReturned.size() != 0 && !currReturned.peek().isGrouper()) {
- group.add(currReturned.pop());
- }
-
- while (opStack.size() != 0 && !opStack.peek().isGrouper()) {
- group.add(opStack.pop());
- }
-
- if (currReturned.size() == 0) {
- Errors.inst.printError(EK_SHUNT_INVSEP);
- return false;
- }
-
- currReturned.addLast(new Token(TOKGROUP, group));
- } else {
- currReturned.addLast(tk);
- }
-
- return true;
- }
-
- /* Check if an operator has higher precedence. */
- private boolean isHigherPrec(final Token lft, final Token rght) {
- final Token.Type left = lft.type;
- final Token.Type right = rght.type;
-
- boolean exists = ops.containsKey(right);
-
- if (rght.type == TAGOPR) {
- exists = true;
- }
-
- /* If it doesn't, the left is higher precedence. */
- if (!exists) {
- return false;
- }
-
- int rightPrecedence;
- int leftPrecedence;
-
- if (rght.type == TAGOPR) {
- rightPrecedence = (int) rght.intValue;
- } else {
- rightPrecedence = ops.get(right);
- }
-
- if (lft.type == TAGOPR) {
- leftPrecedence = (int) lft.intValue;
- } else {
- leftPrecedence = ops.get(left);
- }
-
- if (rightAssoc.contains(left)) {
- return rightPrecedence > leftPrecedence;
- }
-
- return rightPrecedence >= leftPrecedence;
- }
-
- /* Check if something is an operator. */
- private boolean isOp(final Token tk) {
- final Token.Type ty = tk.type;
-
- if (ops.containsKey(ty)) {
- return true;
- }
-
- if (unaryAdjectives.contains(ty)) {
- return true;
- }
-
- if (unaryAdverbs.contains(ty)) {
- return true;
- }
-
- if (unaryGerunds.contains(ty)) {
- return true;
- }
-
- if (ty == TAGOPR) {
- return true;
- }
-
- return false;
- }
-
- /* Check if something is a unary operator. */
- private boolean isUnary(final Token tk) {
- final Token.Type ty = tk.type;
-
- if (unaryAdjectives.contains(ty)) {
- return true;
- }
-
- if (unaryAdverbs.contains(ty)) {
- return true;
- }
-
- if (unaryGerunds.contains(ty)) {
- return true;
- }
-
- return false;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Token.java b/dice-lang/src/bjc/dicelang/Token.java
deleted file mode 100644
index 2841973..0000000
--- a/dice-lang/src/bjc/dicelang/Token.java
+++ /dev/null
@@ -1,149 +0,0 @@
-package bjc.dicelang;
-
-import bjc.dicelang.dice.DieExpression;
-import bjc.utils.funcdata.IList;
-
-/*
- * @TODO 10/09/17 Ben Culkin :TokenReorg
- * Split the class into subclasses based off of type.
- */
-/**
- * Lexer token.
- */
-@SuppressWarnings("javadoc")
-public class Token {
- public final static Token NIL_TOKEN = new Token(Type.NIL);
-
- /**
- * Possible token types
- */
- public static enum Type {
- // Natural tokens
- // These are produced from lexemes
- ADD, SUBTRACT, MULTIPLY, DIVIDE, IDIVIDE, INT_LIT, FLOAT_LIT, STRING_LIT, VREF, DICE_LIT, DICESCALAR, DICEFUDGE, DICEGROUP, DICECONCAT, DICELIST, LET, BIND, COERCE, STRCAT, STRREP, OPAREN, CPAREN, OBRACKET, CBRACKET, OBRACE, CBRACE,
-
- // Synthetic tokens
- // These are produced when needed
- NIL, GROUPSEP, TOKGROUP, TAGOP, TAGOPR
- }
-
- public final Type type;
-
- // This is used for the following token types
- // INT_LIT (int value)
- // STRING_LIT (index into string table)
- // VREF (index into sym table)
- // O* and C* (sym-count of current token)
- public long intValue;
-
- // This is used for the following token types
- // FLOAT_LIT (float value)
- public double floatValue;
-
- // This is used for the following token types
- // DICE_LIT (dice value)
- public DieExpression diceValue;
-
- // This is used for the following token types
- // TOKGROUP (the tokens in the group)
- // TAG* (the tagged construct)
- public IList<Token> tokenValues;
-
- public Token(final Type typ) {
- type = typ;
- }
-
- public Token(final Type typ, final long val) {
- this(typ);
-
- intValue = val;
- }
-
- public Token(final Type typ, final double val) {
- this(typ);
-
- floatValue = val;
- }
-
- public Token(final Type typ, final DieExpression val) {
- this(typ);
-
- diceValue = val;
- }
-
- public Token(final Type typ, final IList<Token> tkVals) {
- this(typ);
-
- tokenValues = tkVals;
- }
-
- @Override
- public String toString() {
- switch (type) {
- case INT_LIT:
- case STRING_LIT:
- case VREF:
- case OPAREN:
- case CPAREN:
- case OBRACKET:
- case CBRACKET:
- case OBRACE:
- case CBRACE:
- return type.toString() + "(" + intValue + ")";
-
- case FLOAT_LIT:
- return type.toString() + "(" + floatValue + ")";
-
- case DICE_LIT:
- return type.toString() + "(" + diceValue + ")";
-
- case TAGOP:
- case TAGOPR:
- case TOKGROUP:
- return type.toString() + "(" + tokenValues + ")";
-
- default:
- return type.toString();
- }
- }
-
- @Override
- public boolean equals(final Object other) {
- if (!(other instanceof Token)) {
- return false;
- }
-
- final Token otk = (Token) other;
-
- if (otk.type != type) {
- return false;
- }
-
- switch (type) {
- case OBRACE:
- case OBRACKET:
- return intValue == otk.intValue;
-
- default:
- return true;
- }
- }
-
- public boolean isGrouper() {
- switch (type) {
- case OPAREN:
- case OBRACE:
- case OBRACKET:
- return true;
-
- default:
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- // TODO Auto-generated method stub
- return super.hashCode();
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/Tokenizer.java b/dice-lang/src/bjc/dicelang/Tokenizer.java
deleted file mode 100644
index 3e4a490..0000000
--- a/dice-lang/src/bjc/dicelang/Tokenizer.java
+++ /dev/null
@@ -1,174 +0,0 @@
-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.*;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import bjc.dicelang.dice.DiceBox;
-import bjc.utils.funcdata.FunctionalMap;
-import bjc.utils.funcdata.IMap;
-import bjc.utils.funcutils.StringUtils;
-import bjc.utils.parserutils.TokenUtils;
-
-/**
- * Converts strings into tokens.
- */
-public class Tokenizer {
- /* Literal tokens for tokenization */
- private final IMap<String, Token.Type> litTokens;
-
- private final DiceLangEngine eng;
-
- private int nextSym = 0;
-
- public Tokenizer(final DiceLangEngine engine) {
- eng = engine;
-
- 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(".+.", STRCAT);
- litTokens.put(".*.", STRREP);
- litTokens.put(",", GROUPSEP);
- litTokens.put("crc", COERCE);
- }
-
- public Token lexToken(final String token, final IMap<String, String> stringLts) {
- if (token.equals("")) {
- return null;
- }
-
- Token tk = Token.NIL_TOKEN;
-
- if (litTokens.containsKey(token)) {
- tk = new Token(litTokens.get(token));
- } else {
- switch (token.charAt(0)) {
- case '(':
- case ')':
- case '[':
- case ']':
- case '{':
- case '}':
- tk = tokenizeGrouping(token);
- break;
- default:
- tk = tokenizeLiteral(token, stringLts);
- }
- }
-
- return tk;
- }
-
- private static Token tokenizeGrouping(final String token) {
- Token tk = Token.NIL_TOKEN;
-
- if (StringUtils.containsOnly(token, "\\" + token.charAt(0))) {
- /* Handle multiple-grouped delimiters. */
- switch (token.charAt(0)) {
- 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;
- }
- }
-
- return tk;
- }
-
- /* Patterns for matching. */
- private final Pattern hexadecimalMatcher =
- Pattern.compile("\\A[\\-\\+]?0x[0-9A-Fa-f]+\\Z");
- private final Pattern flexadecimalMatcher =
- Pattern.compile("\\A[\\-\\+]?[0-9][0-9A-Za-z]+B\\d{1,2}\\Z");
- private final Pattern stringLitMatcher =
- Pattern.compile("\\AstringLiteral(\\d+)\\Z");
-
- /* Tokenize a literal value. */
- 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;
- }
-
- final String flexNum = token.substring(0, token.lastIndexOf('B'));
-
- try {
- tk = new Token(INT_LIT, Long.parseLong(flexNum, parseBase));
- } catch (final NumberFormatException nfex) {
- Errors.inst.printError(EK_TOK_INVFLEX, flexNum, Integer.toString(parseBase));
- return Token.NIL_TOKEN;
- }
- } else if (TokenUtils.isDouble(token)) {
- tk = new Token(FLOAT_LIT, Double.parseDouble(token));
- } else if (DiceBox.isValidExpression(token)) {
- tk = new Token(DICE_LIT, DiceBox.parseExpression(token));
- } else {
- final Matcher stringLit = stringLitMatcher.matcher(token);
-
- if (stringLit.matches()) {
- final int litNum = Integer.parseInt(stringLit.group(1));
-
- eng.addStringLiteral(litNum, stringLts.get(token));
- tk = new Token(STRING_LIT, litNum);
- } else {
- /* 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
deleted file mode 100644
index 0793872..0000000
--- a/dice-lang/src/bjc/dicelang/dice/CompoundDie.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A die whose rolls result from concatenating two other rolls together.
- *
- * @author Ben Culkin
- */
-public class CompoundDie implements Die {
- /* The dice that form this die */
- private final Die left;
- private final Die right;
-
- /**
- * Create a new compound die.
- *
- * @param lft
- * The left die
- * @param rght
- * The right die
- */
- public CompoundDie(final Die lft, final Die rght) {
- left = lft;
- right = rght;
- }
-
- @Override
- public boolean canOptimize() {
- return left.canOptimize() && right.canOptimize();
- }
-
- @Override
- public long optimize() {
- long leftOpt = left.optimize();
- long rightOpt = right.optimize();
-
- return Long.parseLong(String.format("%d%d", leftOpt, rightOpt));
- }
-
- @Override
- public long roll() {
- long leftRoll = left.optimize();
- long rightRoll = right.optimize();
-
- return Long.parseLong(String.format("%d%d", leftRoll, rightRoll));
- }
-
- @Override
- public long rollSingle() {
- /* Actually one dice built using two, can't be split. */
- return roll();
- }
-
- @Override
- public String 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
deleted file mode 100644
index 023282e..0000000
--- a/dice-lang/src/bjc/dicelang/dice/CompoundingDie.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package bjc.dicelang.dice;
-
-import java.util.function.Predicate;
-
-/**
- * Implements a compounding die.
- *
- * This means that the source will be rolled, and then more single rolls will be
- * added while it meets a qualification.
- *
- * @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;
-
- /**
- * Create a new compounding die with no pattern.
- *
- * @param src
- * The die to compound from
- * @param compound
- * The conditions to compound on
- */
- public CompoundingDie(final Die src, final Predicate<Long> compound) {
- this(src, compound, null);
- }
-
- /**
- * Create a new compounding die with a specified pattern.
- *
- * @param src
- * The die to compound from
- * @param compound
- * The conditions to compound on
- * @param patt
- * The string pattern the condition came from, for
- * printing
- */
- public CompoundingDie(final Die src, final Predicate<Long> compound, final String patt) {
- source = src;
-
- compoundOn = compound;
- compoundPattern = patt;
- }
-
- @Override
- public boolean canOptimize() {
- 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;
- }
-
- return res;
- }
-
- @Override
- public long rollSingle() {
- /* 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;
- }
-
- return res;
- }
-
- @Override
- public String toString() {
- String sourceString = source.toString();
-
- /* Can't print a parseable version. */
- if (compoundPattern == null) {
- return String.format("%s!!<complex-pattern>", sourceString);
- }
-
- 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
deleted file mode 100644
index 8d00d96..0000000
--- a/dice-lang/src/bjc/dicelang/dice/DiceBox.java
+++ /dev/null
@@ -1,310 +0,0 @@
-package bjc.dicelang.dice;
-
-import java.util.Random;
-import java.util.function.Predicate;
-import java.util.regex.Pattern;
-
-/**
- * Contains static methods for producing dice from strings.
- *
- * @author Ben Culkin
- */
-public class DiceBox {
- static final Random rng = new Random();
-
- /**
- * Parse a die expression from a string.
- *
- * @param expString
- * The string to parse.
- *
- * @return The die expression from the string, or null if it wasn't one
- */
- public static DieExpression parseExpression(final String expString) {
- 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.
- */
- String exMessage = ex.getMessage();
-
- System.out.printf("ERROR: Could not parse die expression (Cause: %s)\n", exMessage);
- 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. */
- /* @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 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. */
- final String[] dieParts = expString.split("d");
-
- final long right = Long.parseLong(dieParts[1]);
- final long left;
-
- if (dieParts[0].equals("")) {
- /* Handle short-form expressions. */
- left = 1;
- } else {
- left = Long.parseLong(dieParts[0]);
- }
-
- final Die scal = new SimpleDie(left, right);
-
- return new DieExpression(scal);
- } else if (fudgeDiePattern.matcher(expString).matches()) {
- /* Parse fudge dice. */
- /* :SubstringIndexOf */
- final String nDice = expString.substring(0, expString.indexOf('d'));
- final Die fudge = new FudgeDie(Long.parseLong(nDice));
-
- return new DieExpression(fudge);
- } else if (compoundDiePattern.matcher(expString).matches()) {
- /* Parse compound die expressions. */
- final String[] dieParts = expString.split("c");
-
- /* @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. */
- final String[] dieParts = expString.split("!!");
-
- 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. */
- final String[] dieParts = expString.split("!");
-
- 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. */
- final String[] dieParts = expString.split("p!");
-
- 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. */
- final String[] dieParts = expString.split("dl");
-
- 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. */
- /* @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+";
-
- /*
- * Defines a scalar die.
- *
- * This is just a number.
- */
- private static final String scalarDie = "[\\+\\-]?\\d+sd";
- private static final Pattern scalarDiePattern = Pattern.compile(
- String.format("\\A%s\\Z", scalarDie));
-
- /*
- * Defines a simple die.
- *
- * This is a group of one or more dice of the same size.
- */
- private static final String simpleDie = "(?:\\d+)?d\\d+";
- private static final Pattern simpleDiePattern = Pattern.compile("\\A" +
- simpleDie + "\\Z");
-
- /*
- * Defines a fudge die.
- *
- * This is like a simple die, but all the die give -1, 0, or 1 as
- * results.
- */
- private static final String fudgeDie = "(?:\\d+)?dF";
- private static final Pattern fudgeDiePattern = Pattern.compile("\\A" + fudgeDie +
- "\\Z");
-
- /*
- * Defines a compound die.
- *
- * This is like using two d10's to simulate a d100
- */
- private static final String compoundDie = simpleDie + "c(?:(?:" +
- simpleDie + ")|(?:\\d+))";
- private static final Pattern compoundDiePattern = Pattern.compile("\\A" +
- compoundDie + "\\Z");
-
- /*
- * Defines a compound group.
- *
- * This is used for forming die list type expressions.
- */
- private static final String compoundGroup = "(?:(?:" + scalarDie + ")|(?:" + simpleDie +
- ")|(?:" + compoundDie
- + ")|(?:" + fudgeDie + "))";
-
- /*
- * Defines a compounding die.
- *
- * This is like an exploding die, but is a single die, not a group of
- * them.
- */
- private static final String compoundingDie = compoundGroup + "!!" +
- comparePoint;
- private static final Pattern compoundingDiePattern = Pattern.compile("\\A" +
- compoundingDie + "\\Z");
-
- /*
- * Defines an exploding die.
- *
- * This is a die that you reroll the component of if it meets a certain
- * condition.
- */
- private static final String explodingDie = compoundGroup + "!" +
- comparePoint;
- private static final Pattern explodingDiePattern = Pattern.compile("\\A" +
- explodingDie + "\\Z");
-
- /*
- * Defines a penetrating die.
- *
- * This is like an exploding die, but the exploded result gets a -1
- * penalty.
- */
- private static final String penetratingDie = compoundGroup + "!" +
- comparePoint;
- private static final Pattern penetratingDiePattern = Pattern.compile("\\A" +
- penetratingDie + "\\Z");
-
- /*
- * Defines a die list.
- *
- * This is an array of dice of the specified size.
- */
- private static final String diceList = compoundGroup + "dl" + compoundGroup;
- private static final Pattern diceListPattern = Pattern.compile("\\A" + diceList +
- "\\Z");
-
- /**
- * Check if a given string is a valid die expression.
- *
- * @param exp
- * The string to check validity of.
- *
- * @return Whether or not the string is a valid command.
- */
- public static boolean isValidExpression(final String exp) {
- /* @NOTE
- * Should this matcher/matches expression be abstracted in
- * some way?
- */
- if (scalarDiePattern.matcher(exp).matches()) {
- return true;
- } else if (simpleDiePattern.matcher(exp).matches()) {
- return true;
- } else if (fudgeDiePattern.matcher(exp).matches()) {
- return true;
- } else if (compoundDiePattern.matcher(exp).matches()) {
- return true;
- } else if (compoundingDiePattern.matcher(exp).matches()) {
- return true;
- } else if (explodingDiePattern.matcher(exp).matches()) {
- return true;
- } else if (penetratingDiePattern.matcher(exp).matches()) {
- return true;
- } else if (diceListPattern.matcher(exp).matches()) {
- return true;
- } else {
- return false;
- }
- }
-
- /* Derive a predicate from a compare point */
- private static Predicate<Long> deriveCond(final String patt) {
- final long num = Long.parseLong(patt.substring(1));
-
- /* @NOTE
- * Should this be extended in some way, to provide other
- * operators?
- */
- switch (patt.charAt(0)) {
- case '<':
- return (roll) -> (roll < num);
- case '=':
- return (roll) -> (roll == num);
- case '>':
- return (roll) -> (roll > num);
- default:
- return (roll) -> (false);
- }
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/Die.java b/dice-lang/src/bjc/dicelang/dice/Die.java
deleted file mode 100644
index 630e8b9..0000000
--- a/dice-lang/src/bjc/dicelang/dice/Die.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * Represents one or more dice that produce a scalar result.
- *
- * @author Ben Culkin
- */
-public interface Die {
- /**
- * Can this die be optimized to a single number?
- *
- * @return Whether this die can be optimized or not.
- */
- boolean canOptimize();
-
- /**
- * Optimize this die to a single number.
- *
- * Calling optimize on dice that return false for canOptimize produces
- * undefined behavior
- *
- * @return The optimized form of this die
- */
- long optimize();
-
- /**
- * Roll this die.
- *
- * @return A possible roll of this die
- */
- long roll();
-
- /**
- * Roll only a single portion of this die.
- *
- * @return A possible roll of a single portion of this die.
- */
- long rollSingle();
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/DieExpression.java b/dice-lang/src/bjc/dicelang/dice/DieExpression.java
deleted file mode 100644
index b8faeda..0000000
--- a/dice-lang/src/bjc/dicelang/dice/DieExpression.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package bjc.dicelang.dice;
-
-import java.util.Arrays;
-
-/*
- * @NOTE
- * I'm not a particularly large fan of sticking everything on this class
- * and just documenting which fields are tied together in a non-obvious
- * way. I think a class hierarchy might be better, but I am unsure of the
- * details.
- */
-/**
- * Represents either a die or a die list.
- *
- * @author Ben Culkin
- */
-public class DieExpression {
- /** Is this expression a list? */
- public final boolean isList;
-
- /** The scalar value in this expression, if there is one. */
- public Die scalar;
- /** The list value in this expression, if there is one. */
- public DieList list;
-
- /**
- * Create a scalar die expression.
- *
- * @param scal
- * The scalar value of this expression.
- */
- public DieExpression(final Die scal) {
- isList = false;
- scalar = scal;
- }
-
- /**
- * Create a list die expression.
- *
- * @param lst
- * The list value of this expression.
- */
- public DieExpression(final DieList lst) {
- isList = true;
- list = lst;
- }
-
- @Override
- public String toString() {
- if (isList) {
- return list.toString();
- }
-
- return scalar.toString();
- }
-
- /**
- * Get the value of this expression as a string.
- *
- * @return The value of the expression as a string.
- */
- public String value() {
- if (isList) {
- return Arrays.toString(list.roll());
- }
-
- return Long.toString(scalar.roll());
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/DieList.java b/dice-lang/src/bjc/dicelang/dice/DieList.java
deleted file mode 100644
index 48006d4..0000000
--- a/dice-lang/src/bjc/dicelang/dice/DieList.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * Represents a group of dice.
- *
- * @author Ben Culkin.
- */
-public interface DieList {
- /**
- * Can this list be optimized?
- *
- * @return Whether or not this list can be optimized.
- */
- boolean canOptimize();
-
- /**
- * Optimize this list, if it can be done.
- *
- * Invoking this on unoptimizable expression is undefined.
- *
- * @return The optimized form of this list.
- */
- long[] optimize();
-
- /**
- * Roll this group of dice.
- *
- * @return A possible roll of this group.
- */
- long[] roll();
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/ExplodingDice.java b/dice-lang/src/bjc/dicelang/dice/ExplodingDice.java
deleted file mode 100644
index e891a1c..0000000
--- a/dice-lang/src/bjc/dicelang/dice/ExplodingDice.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package bjc.dicelang.dice;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * An exploding die.
- *
- * Represents a die list that keeps getting another added die as long as a
- * condition is met.
- *
- * @author Ben Culkin
- */
-public class ExplodingDice implements DieList {
- /* The source die to use. */
- private final Die source;
-
- /* The conditions for exploding. */
- private final Predicate<Long> explodeOn;
- private final String explodePattern;
- /* Whether or not to apply a -1 penalty to explosions. */
- private final boolean explodePenetrates;
-
- /**
- * Create a new exploding die.
- *
- * @param src
- * The source die for exploding.
- * @param explode
- * The condition to explode on.
- */
- public ExplodingDice(final Die src, final Predicate<Long> explode) {
- this(src, explode, null, false);
- }
-
- /**
- * Create a new exploding die that may penetrate.
- *
- * @param src
- * The source die for exploding.
- * @param explode
- * The condition to explode on.
- * @param penetrate
- * Whether or not for explosions to penetrate (-1 to
- * exploded die).
- */
- public ExplodingDice(final Die src, final Predicate<Long> explode,
- final boolean penetrate) {
- this(src, explode, null, penetrate);
- }
-
- /**
- * Create a new exploding die that may penetrate.
- *
- * @param src
- * The source die for exploding.
- * @param explode
- * The condition to explode on.
- * @param penetrate
- * Whether or not for explosions to penetrate (-1 to
- * exploded die).
- * @param patt
- * The string the condition came from, for printing.
- */
- public ExplodingDice(final Die src, final Predicate<Long> explode, final String patt,
- final boolean penetrate) {
- source = src;
- explodeOn = explode;
- explodePattern = patt;
- explodePenetrates = penetrate;
- }
-
- @Override
- public boolean canOptimize() {
- return false;
- }
-
- @Override
- public long[] optimize() {
- return new long[0];
- }
-
- @Override
- public long[] roll() {
- final long res = source.roll();
- long oldRes = res;
-
- final List<Long> resList = new LinkedList<>();
- resList.add(res);
-
- while (explodeOn.test(oldRes)) {
- oldRes = source.rollSingle();
-
- if (explodePenetrates) {
- oldRes -= 1;
- }
-
- resList.add(oldRes);
- }
-
- final long resArr[] = new long[resList.size()];
-
- int i = 0;
- for(long rll : resList) {
- resArr[i] = rll;
- i += 1;
- }
-
- return resArr;
- }
-
- @Override
- public String toString() {
- String penString = explodePenetrates ? "p" : "";
- String sourceString = source.toString();
-
- if (explodePattern == null) {
- return String.format("%s%s!<complex-pred>", sourceString, penString);
- }
-
- return String.format("%s%s!%s", sourceString, penString, explodePattern);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/FudgeDie.java b/dice-lang/src/bjc/dicelang/dice/FudgeDie.java
deleted file mode 100644
index 23951b2..0000000
--- a/dice-lang/src/bjc/dicelang/dice/FudgeDie.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A fudge die, one that has -1, 0 and 1 as its sides.
- *
- * @author EVE
- *
- */
-public class FudgeDie implements Die {
- /* The number of dice to roll. */
- private final Die numDice;
-
- /**
- * Create a new fudge die.
- *
- * @param nDice
- * The number of dice to roll.
- */
- public FudgeDie(final long nDice) {
- numDice = new ScalarDie(nDice);
- }
-
- /**
- * Create a new fudge die.
- *
- * @param nDice
- * The number of dice to roll.
- */
- public FudgeDie(final Die nDice) {
- numDice = nDice;
- }
-
- @Override
- public boolean canOptimize() {
- return numDice.canOptimize() && numDice.optimize() == 0;
- }
-
- @Override
- public long optimize() {
- return 0;
- }
-
- @Override
- public long roll() {
- long res = 0;
-
- final long nDice = numDice.roll();
-
- for (int i = 0; i < nDice; i++) {
- res += rollSingle();
- }
-
- return res;
- }
-
- @Override
- public long rollSingle() {
- return DiceBox.rng.nextInt(3) - 1;
- }
-
- @Override
- public String toString() {
- String dieString = numDice.toString();
-
- return String.format("%sdF", dieString);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/MathDie.java b/dice-lang/src/bjc/dicelang/dice/MathDie.java
deleted file mode 100644
index e4f2953..0000000
--- a/dice-lang/src/bjc/dicelang/dice/MathDie.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A die that represents two dice with an applied math operator.
- *
- * @author EVE
- *
- */
-public class MathDie implements Die {
- /*
- * @TODO 10/08/17 Ben Culkin :MathGeneralize
- * Why do we have the operator types hardcoded, instead of just
- * having a general thing for applying a binary operator to dice?
- * Fix this by changing it to the more general form.
- */
- /**
- * The types of a math operator.
- *
- * @author EVE
- *
- */
- public static enum MathOp {
- /** Add two dice. */
- ADD,
- /** Subtract two dice. */
- SUBTRACT,
- /** Multiply two dice. */
- MULTIPLY;
-
- @Override
- public String toString() {
- switch (this) {
- case ADD:
- return "+";
-
- case SUBTRACT:
- return "-";
-
- case MULTIPLY:
- return "*";
-
- default:
- return this.name();
- }
- }
- }
-
- private final MathDie.MathOp type;
-
- private final Die left;
- private final Die right;
-
- /**
- * Create a new math die.
- *
- * @param op
- * The operator to apply.
- *
- * @param lft
- * The left operand.
- *
- * @param rght
- * The right operand.
- */
- public MathDie(final MathDie.MathOp op, final Die lft, final Die rght) {
- type = op;
-
- left = lft;
- right = rght;
- }
-
- @Override
- public boolean canOptimize() {
- return left.canOptimize() && right.canOptimize();
- }
-
- private long performOp(final long lft, final long rght) {
- switch (type) {
- case ADD:
- return lft + rght;
-
- case SUBTRACT:
- return lft - rght;
-
- case MULTIPLY:
- return lft * rght;
-
- default:
- return 0;
- }
- }
-
- @Override
- public long optimize() {
- final long lft = left.optimize();
- final long rght = right.optimize();
-
- return performOp(lft, rght);
- }
-
- @Override
- public long roll() {
- final long lft = left.roll();
- final long rght = right.roll();
-
- return performOp(lft, rght);
- }
-
- @Override
- public long rollSingle() {
- final long lft = left.rollSingle();
- final long rght = right.rollSingle();
-
- return performOp(lft, rght);
- }
-
- @Override
- public String toString() {
- return left.toString() + " " + type.toString() + " " + right.toString();
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/ScalarDie.java b/dice-lang/src/bjc/dicelang/dice/ScalarDie.java
deleted file mode 100644
index cbe9d3f..0000000
--- a/dice-lang/src/bjc/dicelang/dice/ScalarDie.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A scalar die, that always returns a given number.
- *
- * @author EVE
- *
- */
-public class ScalarDie implements Die {
- /* The die value. */
- private final long val;
-
- /**
- * Create a new scalar die with a set value.
- *
- * @param vl
- * The value to use.
- */
- public ScalarDie(final long vl) {
- val = vl;
- }
-
- @Override
- public boolean canOptimize() {
- return true;
- }
-
- @Override
- public long optimize() {
- return val;
- }
-
- @Override
- public long roll() {
- return val;
- }
-
- @Override
- public long rollSingle() {
- return val;
- }
-
- @Override
- public String toString() {
- return String.format("%d", val);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/SimpleDie.java b/dice-lang/src/bjc/dicelang/dice/SimpleDie.java
deleted file mode 100644
index 6cae423..0000000
--- a/dice-lang/src/bjc/dicelang/dice/SimpleDie.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A simple group of dice.
- *
- * @author EVE
- *
- */
-public class SimpleDie implements Die {
- /* The number of dice to roll. */
- private final Die numDice;
- /*
- * The size of each dice to roll.
- *
- * Rolled once per role, not once for each dice rolled.
- *
- * @NOTE
- * Would having some way to roll it once for each dice rolled be
- * useful in any sort of case?
- */
- private final Die diceSize;
-
- /**
- * Create a new dice group.
- *
- * @param nDice
- * The number of dice.
- *
- * @param size
- * The size of the dice.
- */
- public SimpleDie(final long nDice, final long size) {
- this(new ScalarDie(nDice), new ScalarDie(size));
- }
-
- /**
- * Create a new dice group.
- *
- * @param nDice
- * The number of dice.
- *
- * @param size
- * The size of the dice.
- */
- public SimpleDie(final Die nDice, final long size) {
- this(nDice, new ScalarDie(size));
- }
-
- /**
- * Create a new dice group.
- *
- * @param nDice
- * The number of dice.
- *
- * @param size
- * The size of the dice.
- */
- public SimpleDie(final long nDice, final Die size) {
- this(new ScalarDie(nDice), size);
- }
-
- /**
- * Create a new dice group.
- *
- * @param nDice
- * The number of dice.
- *
- * @param size
- * The size of the dice.
- */
- public SimpleDie(final Die nDice, final Die size) {
- numDice = nDice;
- diceSize = size;
- }
-
- @Override
- public boolean canOptimize() {
- if (diceSize.canOptimize() && diceSize.optimize() <= 1) {
- return numDice.canOptimize();
- }
-
- return false;
- }
-
- @Override
- public long optimize() {
- final long optSize = diceSize.optimize();
-
- if (optSize == 0) {
- return 0;
- }
-
- return numDice.optimize();
- }
-
- @Override
- public long roll() {
- long total = 0;
-
- final long nDice = numDice.roll();
- final long dSize = diceSize.roll();
-
- for (int i = 0; i < nDice; i++) {
- total += Math.abs(DiceBox.rng.nextLong()) % dSize + 1;
- }
-
- return total;
- }
-
- @Override
- public long rollSingle() {
- return Math.abs(DiceBox.rng.nextLong()) % diceSize.roll() + 1;
- }
-
- @Override
- public String toString() {
- return numDice + "d" + diceSize;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/dice/SimpleDieList.java b/dice-lang/src/bjc/dicelang/dice/SimpleDieList.java
deleted file mode 100644
index 8391054..0000000
--- a/dice-lang/src/bjc/dicelang/dice/SimpleDieList.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package bjc.dicelang.dice;
-
-/**
- * A simple list of dice.
- *
- * @author EVE
- *
- * @TODO 10/08/17 Ben Culkin :DieListGeneralize
- * DieList in general should be changed to be able to be
- * constructed from an arbitrary die using rollSingle and things
- * like that.
- */
-public class SimpleDieList implements DieList {
- /* The number of dice to roll. */
- private final Die numDice;
- /*
- * The size of each die to roll.
- *
- * Checked once per roll, not once per dice rolled.
- */
- private final Die size;
-
- /**
- * Create a new list of dice.
- *
- * @param nDice
- * The number of dice in the list.
- *
- * @param sze
- * The size of dice in the list.
- */
- public SimpleDieList(final Die nDice, final Die sze) {
- numDice = nDice;
- size = sze;
- }
-
- @Override
- public boolean canOptimize() {
- if (size.canOptimize() && size.optimize() <= 1) {
- return numDice.canOptimize();
- }
-
- return false;
- }
-
- @Override
- public long[] optimize() {
- final int sze = (int) numDice.optimize();
- final long res = size.optimize();
-
- final long[] ret = new long[sze];
-
- for (int i = 0; i < sze; i++) {
- ret[i] = res;
- }
-
- return ret;
- }
-
- @Override
- public long[] roll() {
- final int num = (int) numDice.roll();
-
- final long[] ret = new long[num];
-
- for (int i = 0; i < num; i++) {
- ret[i] = size.roll();
- }
-
- return ret;
- }
-
- @Override
- public String toString() {
- return numDice.toString() + "dl" + size.toString();
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/Ezpr.java b/dice-lang/src/bjc/dicelang/expr/Ezpr.java
deleted file mode 100644
index 862c097..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Ezpr.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * @TODO 10/08/17 Ben Culkin :EzprFixing
- * Implement these, and make sure they work correctly.
- */
-// package bjc.dicelang.expr;
-
-// import bjc.utils.data.ITree;
-
-// 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.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 static class EzprNode {
-// public static enum EzprNodeType {
-// EZPR, TOKEN
-// }
-
-// public final EzprNodeType typ;
-
-// public final Ezpr ezp;
-// public final Token tok;
-
-// public EzprNode(Ezpr exp) {
-// typ = EZPR;
-
-// ezp = exp;
-// tok = null;
-// }
-
-// public EzprNode(Token tk) {
-// typ = TOKEN;
-
-// tok = tk;
-// ezp = null;
-// }
-
-// public String toString() {
-// if(typ == TOKEN) {
-// return tok.toString();
-// }
-// return ezp.toString();
-// }
-// }
-
-// private EzprType typ;
-
-// private Multiset<EzprNode> positive;
-// private Multiset<EzprNode> negative;
-
-// 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();
-// }
-// }
diff --git a/dice-lang/src/bjc/dicelang/expr/Lexer.java b/dice-lang/src/bjc/dicelang/expr/Lexer.java
deleted file mode 100644
index dfa0f76..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Lexer.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package bjc.dicelang.expr;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import bjc.utils.funcdata.IList;
-import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter;
-
-/*
- * @TODO 10/08/18 :IntExpressions
- * Add support for integer constants, and maybe floating-point ones as well
- * if you feel like. Heck, you could even go for ratio constants and things
- * as well.
- */
-/**
- * Implements the lexer for simple expression operations.
- *
- * @author Ben Culkin
- */
-public class Lexer {
- /* Splitter we use. */
- private final ConfigurableTokenSplitter split;
-
- /** Create a new expression lexer. */
- public Lexer() {
- split = new ConfigurableTokenSplitter(true);
-
- split.addSimpleDelimiters("(", ")");
- split.addSimpleDelimiters("+", "-", "*", "/");
- }
-
- /**
- * Convert a string from a input command to a series of infix tokens.
- *
- * @param inp
- * The input command.
- *
- * @param tks
- * The token state.
- *
- * @return A series of infix tokens representing the command.
- */
- public Token[] lexString(final String inp, final Tokens tks) {
- /* Split tokens on whitespace. */
- final String[] spacedTokens = inp.split("[ \t]");
- /* Tokens to return. */
- final List<Token> tokens = new LinkedList<>();
-
- /* Process each token. */
- for (final String spacedToken : spacedTokens) {
- /* Split on operators. */
- final IList<String> splitTokens = split.split(spacedToken);
- /* Convert strings to tokens. */
- final IList<Token> rawTokens = splitTokens.map(tok -> tks.lexToken(tok, spacedToken));
-
- /* Add tokens to results. */
- rawTokens.forEach(tokens::add);
- }
-
- return tokens.toArray(new Token[0]);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/Parser.java b/dice-lang/src/bjc/dicelang/expr/Parser.java
deleted file mode 100644
index 5fa2d3d..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Parser.java
+++ /dev/null
@@ -1,147 +0,0 @@
-package bjc.dicelang.expr;
-
-import java.util.Arrays;
-import java.util.Scanner;
-
-import bjc.utils.data.ITree;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.parserutils.TreeConstructor;
-
-/**
- * Parser for simple math expressions.
- *
- * @author Ben Culkin
- */
-public class Parser {
- /*
- * @TODO 10/08/17 Ben Culkin :MainSeperation
- * This main method should be moved to its own class.
- */
- /**
- * Main method.
- *
- * @param args
- * Unused CLI args.
- */
- public static void main(final String[] args) {
- /* Create our objects. */
- final Tokens toks = new Tokens();
- final Lexer lex = new Lexer();
-
- /* Prepare our input source. */
- final Scanner scan = new Scanner(System.in);
-
- /* Read initial command. */
- System.out.print("Enter a math expression (blank line to quit): ");
- String ln = scan.nextLine().trim();
-
- /* Enter REPL loop. */
- while (!ln.equals("")) {
- /* Print raw command. */
- System.out.println("Raw command: " + ln);
- System.out.println();
-
- /* Lex command to infix tokens. */
- final Token[] infixTokens = lex.lexString(ln, toks);
- System.out.println("Lexed tokens: ");
- for (final Token tok : infixTokens) {
- System.out.println("\t" + tok);
- }
-
- /* Print out infix expression. */
- System.out.print("Lexed expression: ");
- for (final Token tok : infixTokens) {
- System.out.print(tok.toExpr() + " ");
- }
-
- /* Space stages. */
- System.out.println();
- System.out.println();
-
- /* Shunt infix tokens to postfix tokens. */
- final Token[] postfixTokens = Shunter.shuntTokens(infixTokens);
- System.out.println("Lexed tokens: ");
- for (final Token tok : postfixTokens) {
- System.out.println("\t" + tok);
- }
-
- /* Print out postfix tokens. */
- System.out.print("Shunted expression: ");
- for (final Token tok : postfixTokens) {
- System.out.print(tok.toExpr() + " ");
- }
-
- /* Space stages. */
- System.out.println();
- System.out.println();
-
- /* Construct a list from the array of tokens. */
- final FunctionalList<Token> tokList = new FunctionalList<>(
- Arrays.asList(postfixTokens));
-
- /* Construct a tree from the list of postfixed tokens. */
- final ITree<Token> ast = TreeConstructor.constructTree(tokList,
- tok -> tok.typ.isOperator);
-
- /* Print the tree, then the canonical expression for it. */
- System.out.println("Parsed tree");
- System.out.println(ast.toString());
- System.out.println("\nCanonical expr: " + toCanonicalExpr(ast));
-
- /* Space stages. */
- System.out.println();
- System.out.println();
-
- /* Prompt for a new expression. */
- System.out.print("Enter a math expression (blank line to quit): ");
- /* Read it. */
- ln = scan.nextLine().trim();
- }
-
- /* Cleanup after ourselves. */
- scan.close();
- }
-
- /*
- * Convert an expression to one that uses the smallest necessary amount
- * of parens.
- */
- private static String toCanonicalExpr(final ITree<Token> ast) {
- final Token data = ast.getHead();
-
- if (ast.getChildrenCount() == 0) {
- /* Handle leaf nodes. */
- return data.toExpr();
- }
-
- /* The left/right children. */
- final ITree<Token> left = ast.getChild(0);
- final ITree<Token> right = ast.getChild(1);
-
- /* Recursively canonicalize them. */
- String leftExpr = toCanonicalExpr(left);
- String rightExpr = toCanonicalExpr(right);
-
- /* Add parens if the left was higher priority. */
- if (left.getChildrenCount() == 0) {
- int leftPriority = left.getHead().typ.operatorPriority;
- int dataPriority = data.typ.operatorPriority;
-
- if (leftPriority >= dataPriority) {
- leftExpr = String.format("(%s)", leftExpr);
- }
- }
-
- /* Add parens if the right was higher priority. */
- if (right.getChildrenCount() == 0) {
- int rightPriority = right.getHead().typ.operatorPriority;
- int dataPriority = data.typ.operatorPriority;
-
- if (rightPriority >= dataPriority) {
- rightExpr = String.format("(%s)", rightExpr);
- }
- }
-
- return String.format("%s %s %s", leftExpr, data.toExpr(), rightExpr);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/Shunter.java b/dice-lang/src/bjc/dicelang/expr/Shunter.java
deleted file mode 100644
index 213e473..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Shunter.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package bjc.dicelang.expr;
-
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Converts a infix series of tokens into a prefix series of tokens.
- *
- * @author Ben Culkin
- */
-public class Shunter {
- /*
- * @NOTE
- * Why does this method return an array, and not the list of
- * tokens?
- */
- /**
- * Convert a infix series of tokens to a postfix series of tokens.
- *
- * @param infixTokens
- * The tokens in infix order.
- *
- * @return The tokens in postfix order.
- */
- public static Token[] shuntTokens(final Token[] infixTokens) {
- /* The returned tokens. */
- final List<Token> postfixTokens = new ArrayList<>(infixTokens.length);
-
- /* The current stack of operators. */
- final Deque<Token> opStack = new LinkedList<>();
-
- /* Shunt each token. */
- for (final Token tok : infixTokens) {
- /* Handle operators. */
- if (tok.typ.isOperator) {
- Token curOp = opStack.peek();
-
- /*
- * Check if an operator is higher priority,
- * respecting their left associativity.
- *
- * @NOTE
- * Should this be factored out into a
- * method?
- */
- int leftPriority = tok.typ.operatorPriority;
- int rightPriority;
-
- if (curOp == null) {
- rightPriority = 0;
- } else {
- rightPriority = curOp.typ.operatorPriority;
- }
-
- boolean isHigherPrec = leftPriority >= rightPriority;
-
- /*
- * Pop all operators that are lower precedence
- * than us.
- */
- while (!opStack.isEmpty() && isHigherPrec) {
- postfixTokens.add(opStack.pop());
- curOp = opStack.peek();
-
- leftPriority = tok.typ.operatorPriority;
- if (curOp == null) {
- rightPriority = 0;
- } else {
- rightPriority = curOp.typ.operatorPriority;
- }
-
- isHigherPrec = leftPriority >= rightPriority;
- }
-
- opStack.push(tok);
- } else if (tok.typ == TokenType.OPAREN) {
- opStack.push(tok);
- } else if (tok.typ == TokenType.CPAREN) {
- Token curOp = opStack.peek();
-
- /*
- * Pop things until we find the matching
- * parenthesis.
- */
- while (curOp.typ != TokenType.OPAREN) {
- final Token tk = opStack.pop();
- postfixTokens.add(tk);
- curOp = opStack.peek();
- }
-
- if (!opStack.isEmpty()) {
- opStack.pop();
- }
- } else {
- postfixTokens.add(tok);
- }
- }
-
- /*
- * Flush remaining operators.
- */
- while (!opStack.isEmpty()) {
- postfixTokens.add(opStack.pop());
- }
-
- return postfixTokens.toArray(new Token[0]);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/Token.java b/dice-lang/src/bjc/dicelang/expr/Token.java
deleted file mode 100644
index bf92f97..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Token.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package bjc.dicelang.expr;
-
-/*
- * @TODO 10/08/17 :TokenReorg
- * I am not a fan of this 'having a bunch of subclasses' in one thing I
- * seem to have been doing around this project. This should be multiple
- * subclasses, one for each value for TokenType.
- */
-/**
- * Represents a lexical token.
- *
- * @author Ben Culkin
- */
-public class Token {
- /* The state for this token. */
- private final Tokens tks;
-
- /**
- * The type of the token.
- *
- * Determines which fields have a value.
- */
- public final TokenType typ;
-
- /** The integer value attached to this token. */
- public int intValue;
-
- /** The original string this token was part of. */
- public String rawValue;
-
- /**
- * Create a new token.
- *
- * @param type
- * The type of this token.
- *
- * @param raw
- * The string this token came from.
- *
- * @param toks
- * The state for this token
- */
- public Token(final TokenType type, final String raw, final Tokens toks) {
- this.typ = type;
-
- rawValue = raw;
- tks = toks;
- }
-
- @Override
- public String toString() {
- String typeStr = typ.toString();
- typeStr = String.format("%s (%s)", typeStr, typ.name());
-
- if (typ == TokenType.VREF) {
- typeStr += " (ind. " + intValue;
- typeStr += ", sym. \"" + tks.symbolTable.get(intValue) + "\")";
- }
-
- return String.format("%s (originally from: %s)", typeStr, rawValue);
- }
-
- /**
- * Convert this token into the string representation of it.
- *
- * @return The string representation of it.
- */
- public String toExpr() {
- switch (typ) {
- case ADD:
- return "+";
- case SUBTRACT:
- return "-";
- case MULTIPLY:
- return "*";
- case DIVIDE:
- return "/";
- case VREF:
- return tks.symbolTable.get(intValue);
- case OPAREN:
- return "(";
- case CPAREN:
- return ")";
- default:
- return "???";
- }
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/TokenType.java b/dice-lang/src/bjc/dicelang/expr/TokenType.java
deleted file mode 100644
index ad01917..0000000
--- a/dice-lang/src/bjc/dicelang/expr/TokenType.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package bjc.dicelang.expr;
-
-/**
- * Represents the type of this token.
- *
- * @author Ben Culkin
- */
-public enum TokenType {
- /*
- * @NOTE
- * Do we want to switch to auto-numbering the tokens? They were
- * manually numbered because this was an assignment for PoPL and
- * that was what Dr. Naz wanted.
- */
-
- /** Represents + */
- ADD( 14, true, 0),
- /** Represents - */
- SUBTRACT(15, true, 0),
- /** Represents * */
- MULTIPLY(16, true, 1),
- /** Represents / */
- DIVIDE( 17, true, 1),
-
- /** Represents variable names. */
- VREF(11),
-
- /** Represents ( */
- OPAREN(0, false, 100),
- /** Represents ) */
- CPAREN(0, false, 100);
-
- /** The ID number for this token type. */
- public final int nVal;
-
- /** Whether or not this type of token is an operator. */
- public final boolean isOperator;
- /** The priority of this operator, if it is one. */
- public final int operatorPriority;
-
- /* Create a new token. */
- private TokenType(final int num, final boolean isOp, final int priority) {
- nVal = num;
- isOperator = isOp;
- operatorPriority = priority;
- }
-
- private TokenType(final int num) {
- this(num, false, -1);
- }
-
- @Override
- public String toString() {
- return Integer.toString(nVal);
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/expr/Tokens.java b/dice-lang/src/bjc/dicelang/expr/Tokens.java
deleted file mode 100644
index 287d2b4..0000000
--- a/dice-lang/src/bjc/dicelang/expr/Tokens.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package bjc.dicelang.expr;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Contains per-instance state for token parsing.
- *
- * @author EVE
- *
- */
-public class Tokens {
- /* Contains mappings from variable references to string names. */
- private final Map<Integer, String> symTab;
- /* Reverse index into the symbol table. */
- private final Map<String, Integer> revSymTab;
-
- /** Read-only view on the symbol table. */
- public final Map<Integer, String> symbolTable;
-
- /* Next index into the symbol table. */
- private int nextSym;
-
- /* Mapping from literal tokens to token types. */
- private final Map<String, TokenType> litTokens;
-
- /** Create a new set of tokens. */
- public Tokens() {
- /* Create tables. */
- symTab = new HashMap<>();
- revSymTab = new HashMap<>();
-
- /* Init public view. */
- symbolTable = Collections.unmodifiableMap(symTab);
-
- /* Set sym ID. */
- nextSym = 0;
-
- /*
- * Setup literal mappings.
- *
- * @NOTE
- * Should this be a static member?
- */
- litTokens = new HashMap<>();
- litTokens.put("+", TokenType.ADD);
- litTokens.put("-", TokenType.SUBTRACT);
- litTokens.put("*", TokenType.MULTIPLY);
- litTokens.put("/", TokenType.DIVIDE);
- litTokens.put("(", TokenType.OPAREN);
- litTokens.put(")", TokenType.CPAREN);
- }
-
- /**
- * Convert the string representation of a token into a token.
- *
- * @param tok
- * The string representation of the token.
- * @param raw
- * The original string the token came from.
- *
- * @return The token the string represents.
- */
- public Token lexToken(final String tok, final String raw) {
- if (litTokens.containsKey(tok)) {
- /* Return matching literal token. */
- return new Token(litTokens.get(tok), raw, this);
- }
-
- /* Its a variable reference. */
- return parseVRef(tok, raw);
- }
-
- /* Parse a variable reference. */
- private Token parseVRef(final String tok, final String raw) {
- final Token tk = new Token(TokenType.VREF, raw, this);
-
- if (revSymTab.containsKey(tok)) {
- /* Reuse the entry if it exists. */
- tk.intValue = revSymTab.get(tok);
- } else {
- /* Create a new entry. */
- tk.intValue = nextSym;
-
- /* Record it. */
- symTab.put(nextSym, tok);
- revSymTab.put(tok, nextSym);
-
- /* Next ID. */
- nextSym += 1;
- }
-
- return tk;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java b/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java
deleted file mode 100644
index 649c6fa..0000000
--- a/dice-lang/src/bjc/dicelang/scl/StreamControlConsole.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package bjc.dicelang.scl;
-
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.IList;
-
-import java.util.Iterator;
-import java.util.Scanner;
-
-import java.util.function.Supplier;
-
-/**
- * Implement a SCL REPL
- *
- * @author Ben Culkin
- */
-public class StreamControlConsole {
- /*
- * @TODO 10/08/17 :SCLArgs
- * Do something useful with the CLI args.
- *
- */
- /**
- * Main method
- *
- * @param args
- * Unused CLI args.
- */
- public static void main(String[] args) {
- /*
- * Initialize vars.
- *
- * We can get away with passing the null, because StreamEngine
- * doesn't reference any parts of DiceLangEngine.
- */
- 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): ");
-
- /* Process it. */
- while (scn.hasNextLine()) {
- String ln = scn.nextLine().trim();
-
- if (ln.equals("")) {
- /* Ignore empty lines. */
- break;
- }
-
- /* Break the token into strings. */
- IList<String> res = new FunctionalList<>();
- String[] tokens = ln.split(" ");
-
- /* Run the stream engine on the tokens. */
- boolean succ = sengine.doStreams(tokens, res);
- if (!succ) {
- System.out.printf("ERROR: Stream engine failed for line '%s'\n", ln);
- continue;
- }
-
- /* Run the command through SCL. */
- tokens = res.toArray(new String[res.getSize()]);
- succ = sclengine.runProgram(tokens);
- if (!succ) {
- System.out.printf("ERROR: SCL engine failed for line '%s'\n", ln);
- 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/StreamControlEngine.java b/dice-lang/src/bjc/dicelang/scl/StreamControlEngine.java
deleted file mode 100644
index d5e8b72..0000000
--- a/dice-lang/src/bjc/dicelang/scl/StreamControlEngine.java
+++ /dev/null
@@ -1,546 +0,0 @@
-package bjc.dicelang.scl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import bjc.dicelang.Errors;
-import bjc.utils.esodata.SimpleStack;
-import bjc.utils.esodata.Stack;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.IList;
-import bjc.utils.parserutils.TokenUtils;
-
-import static bjc.dicelang.Errors.ErrorKey.*;
-import static bjc.dicelang.scl.StreamControlEngine.Token.Type.*;
-
-/*
- * @TODO 10/08/17 Ben Culkin :SCLReorg
- * This is a large enough class that it should maybe be split into
- * subclasses.
- */
-/**
- * Runs a Stream Control Language (SCL) program.
- *
- * SCL is a stack-based concatenative language based mostly off of Postscript
- * and Factor, with inspiration from various other languages.
- *
- * @author Ben Culkin
- */
-public class StreamControlEngine {
- /*
- * @TODO 10/08/17 Ben Culkin :TokenSplit
- * Again with the multiple subclasses in one class. Split it so
- * that each subclass only has the fields it needs.
- */
- public static class Token {
- public static enum Type {
- /* Natural tokens. These come directly from strings */
- ILIT, FLIT, BLIT, SQUOTE, DQUOTE, OBRACKET, OBRACE, SYMBOL, WORD,
-
- /* Synthetic tokens. These are produced from special tokens. */
- SLIT, WORDS, ARRAY,
-
- /* Word tokens These are subordinate to WORD tokens */
- /*
- * @NOTE
- * These should really be in their own enum.
- */
- /* Array manipulation */
- MAKEARRAY, MAKEEXEC, MAKEUNEXEC,
- /* Stream manipulation */
- NEWSTREAM, LEFTSTREAM, RIGHTSTREAM, DELETESTREAM, MERGESTREAM,
- /* Stack manipulation */
- STACKCOUNT, STACKEMPTY, DROP, NDROP, NIP, NNIP,
- }
-
- /* The type of this token */
- public Type type;
-
- /* Used for ILIT */
- public long intVal;
- /* Used for FLIT */
- public double floatVal;
- /* Used for BLIT */
- public boolean boolVal;
- /* Used for SYMBOL & SLIT */
- public String stringVal;
- /* Used for WORD */
- public Token tokenVal;
- /* Used for WORDS & ARRAY */
- public IList<Token> tokenVals;
-
- /* Create a new token. */
- public Token(final Type typ) {
- type = typ;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final long iVal) {
- this(typ);
-
- intVal = iVal;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final double dVal) {
- this(typ);
-
- floatVal = dVal;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final boolean bVal) {
- this(typ);
-
- boolVal = bVal;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final String sVal) {
- this(typ);
-
- stringVal = sVal;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final Token tVal) {
- this(typ);
-
- tokenVal = tVal;
- }
-
- /* Create a new token. */
- public Token(final Type typ, final Token.Type tVal) {
- this(typ, new Token(tVal));
- }
-
- /* Create a new token. */
- public Token(final Type typ, final IList<Token> tVals) {
- this(typ);
-
- tokenVals = tVals;
- }
-
- /* Convert a string into a token. */
- public static Token tokenizeString(final String token) {
- if (litTokens.containsKey(token)) {
- return new Token(litTokens.get(token));
- } else if (token.startsWith("\\")) {
- return new Token(SYMBOL, token.substring(1));
- } else if (builtinWords.containsKey(token)) {
- return new Token(WORD, builtinWords.get(token));
- } else if (token.equals("true")) {
- return new Token(BLIT, true);
- } else if (token.equals("false")) {
- return new Token(BLIT, false);
- } else if (TokenUtils.isInt(token)) {
- return new Token(ILIT, Long.parseLong(token));
- } else if (TokenUtils.isDouble(token)) {
- return new Token(FLIT, Double.parseDouble(token));
- } else {
- Errors.inst.printError(EK_SCL_INVTOKEN, token);
- return null;
- }
- }
-
- /* The literal tokens. */
- private static final Map<String, Token.Type> litTokens;
- /* The builtin words. */
- private static final Map<String, Token.Type> builtinWords;
-
- static {
- /* Init literal tokens. */
- litTokens = new HashMap<>();
-
- litTokens.put("'", SQUOTE);
- litTokens.put("\"", DQUOTE);
- litTokens.put("[", OBRACKET);
- litTokens.put("{", OBRACE);
-
- /* Init builtin words. */
- builtinWords = new HashMap<>();
-
- builtinWords.put("makearray", MAKEARRAY);
- builtinWords.put("+stream", NEWSTREAM);
- builtinWords.put(">stream", LEFTSTREAM);
- builtinWords.put("<stream", RIGHTSTREAM);
- builtinWords.put("-stream", DELETESTREAM);
- builtinWords.put("<-stream", MERGESTREAM);
- builtinWords.put("cvx", MAKEEXEC);
- builtinWords.put("cvux", MAKEUNEXEC);
- builtinWords.put("#", STACKCOUNT);
- builtinWords.put("empty?", STACKEMPTY);
- builtinWords.put("drop", DROP);
- builtinWords.put("ndrop", NDROP);
- builtinWords.put("nip", NIP);
- builtinWords.put("nnip", NNIP);
- }
- }
-
- /* The stream engine we're hooked to. */
- private final StreamEngine eng;
-
- /* The current stack state. */
- private final Stack<Token> curStack;
-
- /* Map of user defined words. */
- private final Map<String, Token> words;
-
- /**
- * Create a new stream control engine.
- *
- * @param engine
- * The engine to control.
- */
- public StreamControlEngine(final StreamEngine engine) {
- eng = engine;
-
- words = new HashMap<>();
- curStack = new SimpleStack<>();
- }
-
- /**
- * Run a SCL program.
- *
- * @param tokens
- * The program to run.
- *
- * @return Whether the program executed successfully.
- */
- public boolean runProgram(final String[] tokens) {
- for (int i = 0; i < tokens.length; i++) {
- /* Tokenize each token. */
- final String token = tokens[i];
- final Token tok = Token.tokenizeString(token);
-
- if (tok == null) {
- System.out.printf("ERROR: Tokenization failed for '%s'\n", token);
- return false;
- }
-
- /* Handle token types. */
- switch (tok.type) {
- case SQUOTE:
- /* Handle single-quotes. */
- i = handleSingleQuote(i, tokens);
- if (i == -1) {
- return false;
- }
- break;
- case OBRACKET:
- /* Handle delimited brackets. */
- i = handleDelim(i, tokens, "]");
- if (i == -1) {
- return false;
- }
- break;
- case OBRACE:
- /* Handle delimited braces. */
- i = handleDelim(i, tokens, "}");
- if (i == -1) {
- return false;
- }
- final Token brak = curStack.pop();
- curStack.push(new Token(ARRAY, brak.tokenVals));
- break;
-
- case WORD:
- /* Handle words. */
- if(!handleWord(tok)) {
- System.out.printf("WARNING: Execution of word '%s' failed\n", tok);
- }
- break;
- default:
- /* Put it onto the stack. */
- curStack.push(tok);
- break;
- }
- }
-
- return true;
- }
-
- private boolean handleWord(final Token tk) {
- boolean succ = true;
-
- /* Handle each type of word. */
- /*
- * @NOTE
- * This should probably use something other than a switch
- * statement.
- */
- switch (tk.tokenVal.type) {
- case NEWSTREAM:
- eng.newStream();
- break;
- case LEFTSTREAM:
- succ = eng.leftStream();
- if (!succ) {
- return false;
- }
- break;
- case RIGHTSTREAM:
- succ = eng.rightStream();
- if (!succ) {
- return false;
- }
- break;
- case DELETESTREAM:
- succ = eng.deleteStream();
- if (!succ) {
- return false;
- }
- break;
- case MERGESTREAM:
- succ = eng.mergeStream();
- if (!succ) {
- return false;
- }
- break;
- case MAKEARRAY:
- succ = makeArray();
- if (!succ) {
- return false;
- }
- break;
- case MAKEEXEC:
- succ = toggleExec(true);
- if (!succ) {
- return false;
- }
- break;
- case MAKEUNEXEC:
- succ = toggleExec(false);
- if (!succ) {
- return false;
- }
- break;
- case STACKCOUNT:
- curStack.push(new Token(ILIT, curStack.size()));
- break;
- case STACKEMPTY:
- curStack.push(new Token(BLIT, curStack.empty()));
- break;
- case DROP:
- if (curStack.size() == 0) {
- Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.tokenVal.type.toString());
- return false;
- }
- curStack.drop();
- break;
- case NDROP:
- succ = handleNDrop();
- if (!succ) {
- return false;
- }
- break;
- case NIP:
- if (curStack.size() < 2) {
- Errors.inst.printError(EK_SCL_SUNDERFLOW, tk.tokenVal.type.toString());
- return false;
- }
- curStack.nip();
- break;
- case NNIP:
- succ = handleNNip();
- if (!succ) {
- return false;
- }
- break;
- default:
- Errors.inst.printError(EK_SCL_UNWORD, tk.tokenVal.type.toString());
- return false;
- }
-
- return true;
- }
-
- /* Handle nipping a specified number of items. */
- private boolean handleNNip() {
- final Token num = curStack.pop();
-
- if (num.type != ILIT) {
- Errors.inst.printError(EK_SCL_INVARG, num.type.toString());
- return false;
- }
-
- final int n = (int) num.intVal;
-
- if (curStack.size() < n) {
- Errors.inst.printError(EK_SCL_SUNDERFLOW, NNIP.toString());
- return false;
- }
-
- curStack.nip(n);
- return true;
- }
-
- /* Handle dropping a specified number of items. */
- private boolean handleNDrop() {
- final Token num = curStack.pop();
-
- if (num.type != ILIT) {
- Errors.inst.printError(EK_SCL_INVARG, num.type.toString());
- return false;
- }
-
- final int n = (int) num.intVal;
-
- if (curStack.size() < n) {
- Errors.inst.printError(EK_SCL_SUNDERFLOW, NDROP.toString());
- return false;
- }
-
- curStack.drop(n);
- return true;
- }
-
- /* Handle toggling the executable flag on an array. */
- private boolean toggleExec(final boolean exec) {
- final Token top = curStack.top();
-
- if (exec) {
- if (top.type != ARRAY) {
- Errors.inst.printError(EK_SCL_INVARG, top.toString());
- return false;
- }
-
- top.type = WORDS;
- } else {
- if (top.type != WORDS) {
- Errors.inst.printError(EK_SCL_INVARG, top.toString());
- return false;
- }
-
- top.type = ARRAY;
- }
-
- return true;
- }
-
- /* Handle creating an array. */
- private boolean makeArray() {
- final Token num = curStack.pop();
-
- if (num.type != ILIT) {
- Errors.inst.printError(EK_SCL_INVARG, num.type.toString());
- }
-
- final IList<Token> arr = new FunctionalList<>();
-
- for (int i = 0; i < num.intVal; i++) {
- arr.add(curStack.pop());
- }
-
- curStack.push(new Token(ARRAY, arr));
-
- return true;
- }
-
- /* Handle a delimited series of tokens. */
- private int handleDelim(final int i, final String[] tokens, final String delim) {
- final IList<Token> toks = new FunctionalList<>();
-
- int n = i + 1;
-
- if (n >= tokens.length) {
- Errors.inst.printError(EK_SCL_MMQUOTE);
- return -1;
- }
-
- String tok = tokens[n];
-
- while (!tok.equals(delim)) {
- final Token ntok = Token.tokenizeString(tok);
-
- switch (ntok.type) {
- case SQUOTE:
- n = handleSingleQuote(n, tokens);
- if (n == -1) {
- return -1;
- }
- toks.add(curStack.pop());
- break;
- case OBRACKET:
- n = handleDelim(n, tokens, "]");
- if (n == -1) {
- return -1;
- }
- toks.add(curStack.pop());
- break;
- case OBRACE:
- n = handleDelim(i, tokens, "}");
- if (n == -1) {
- return -1;
- }
- final Token brak = curStack.pop();
- toks.add(new Token(ARRAY, brak.tokenVals));
- break;
- default:
- toks.add(ntok);
- }
-
- /* Move to the next token */
- n += 1;
-
- if (n >= tokens.length) {
- Errors.inst.printError(EK_SCL_MMQUOTE);
- return -1;
- }
-
- tok = tokens[n];
- }
-
- /* Skip the closing bracket */
- n += 1;
-
- /* @NOTE
- * Instead of being hardcoded, this should be a parameter.
- */
- curStack.push(new Token(WORDS, toks));
-
- return n;
- }
-
- /* Handle a single-quoted string. */
- private int handleSingleQuote(final int i, final String[] tokens) {
- final StringBuilder sb = new StringBuilder();
-
- int n = i + 1;
-
- if (n >= tokens.length) {
- Errors.inst.printError(EK_SCL_MMQUOTE);
- return -1;
- }
-
- String tok = tokens[n];
-
- while (!tok.equals("'")) {
- if (tok.matches("\\\\+'")) {
- /* Handle escaped quotes. */
- sb.append(tok.substring(1));
- } else {
- sb.append(tok);
- }
-
- /* Move to the next token */
- n += 1;
-
- if (n >= tokens.length) {
- Errors.inst.printError(EK_SCL_MMQUOTE);
- return -1;
- }
-
- tok = tokens[n];
- }
-
- /*
- * Skip the single quote
- */
- n += 1;
-
- curStack.push(new Token(SLIT, TokenUtils.descapeString(sb.toString())));
-
- return n;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/scl/StreamEngine.java b/dice-lang/src/bjc/dicelang/scl/StreamEngine.java
deleted file mode 100644
index 6e970b7..0000000
--- a/dice-lang/src/bjc/dicelang/scl/StreamEngine.java
+++ /dev/null
@@ -1,266 +0,0 @@
-package bjc.dicelang.scl;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_STRM_INVCOM;
-import static bjc.dicelang.Errors.ErrorKey.EK_STRM_LAST;
-import static bjc.dicelang.Errors.ErrorKey.EK_STRM_NONEX;
-
-import static java.util.logging.Level.*;
-
-import bjc.dicelang.DiceLangEngine;
-import bjc.dicelang.Errors;
-import bjc.utils.esodata.SingleTape;
-import bjc.utils.esodata.Tape;
-import bjc.utils.esodata.TapeLibrary;
-import bjc.utils.funcdata.FunctionalList;
-import bjc.utils.funcdata.IList;
-import bjc.utils.funcutils.ListUtils;
-
-import java.util.Arrays;
-
-/**
- * Implements multiple interleaved parse streams, as well as a command language
- * for the streams.
- *
- * The idea for the interleaved streams came from the language Oozylbub &amp;
- * Murphy, but the command language was my own idea.
- *
- * @author Ben Culkin
- */
-public class StreamEngine {
- /* Whether or not we're doing debugging. */
- public final boolean debug = true;
-
- /* The engine we're attached to. */
- DiceLangEngine eng;
-
- /* Our streams. */
- Tape<IList<String>> streams;
- IList<String> currStream;
-
- /* Saved streams */
- TapeLibrary<IList<String>> savedStreams;
-
- /* Handler for SCL programs */
- private final StreamControlEngine scleng;
-
- /**
- * Create a new stream engine.
- *
- * @param engine
- * The dice engine we're attached to.
- */
- public StreamEngine(final DiceLangEngine engine) {
- eng = engine;
-
- savedStreams = new TapeLibrary<>();
- scleng = new StreamControlEngine(this);
- }
-
- /* Do pre-run (re)initialization. */
- private void init() {
- /* Reinitialize our list of streams. */
- streams = new SingleTape<>();
-
- /* Create an initial stream. */
- currStream = new FunctionalList<>();
- streams.insertBefore(currStream);
- }
-
- /**
- * 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 String[] toks, final IList<String> dest) {
- 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. */
- init();
-
- /* Are we currently quoting things? */
- boolean quoteMode = false;
-
- /* Process each token. */
- for (final String tk : toks) {
- /* Process stream commands. */
- if (tk.startsWith("{@S") && !quoteMode) {
- if (tk.equals("{@SQ}")) {
- /* Start quoting. */
- quoteMode = true;
- } else if (!processCommand(tk)) {
- return false;
- }
- } else {
- if (tk.equals("{@SU}")) {
- /* Stop quoting. */
- quoteMode = false;
- } else if (tk.startsWith("\\") && tk.endsWith("{@SU}")) {
- /* Unquote quoted end. */
- currStream.add(tk.substring(1));
- } else {
- currStream.add(tk);
- }
- }
- }
-
- for (final String tk : currStream) {
- /* Collect tokens from the current stream. */
- dest.add(tk);
- }
-
- return true;
- }
-
- /** Create a new stream. */
- public void newStream() {
- streams.insertAfter(new FunctionalList<>());
- }
-
- /**
- * Move to a stream to the right.
- *
- * @return Whether or not the move was successful.
- */
- public boolean rightStream() {
- if (!streams.right()) {
- Errors.inst.printError(EK_STRM_NONEX);
- return false;
- }
-
- currStream = streams.item();
- return true;
- }
-
- /**
- * Move to a stream to the left.
- *
- * @return Whether or not the move was successful.
- */
- public boolean leftStream() {
- if (!streams.left()) {
- Errors.inst.printError(EK_STRM_NONEX);
- return false;
- }
-
- currStream = streams.item();
- return true;
- }
-
- /**
- * Delete the current stream.
- *
- * @return Whether or not the delete succeeded.
- */
- public boolean deleteStream() {
- if (streams.size() == 1) {
- Errors.inst.printError(EK_STRM_LAST);
- return false;
- }
-
- streams.remove();
- currStream = streams.item();
-
- return true;
- }
-
- /**
- * Merge the current stream into the previous stream.
- *
- * @return Whether or not the merge succeded.
- */
- public boolean mergeStream() {
- if (streams.size() == 1) {
- Errors.inst.printError(EK_STRM_LAST);
- return false;
- }
-
- final IList<String> stringLit = streams.remove();
- currStream = streams.item();
- currStream.add(ListUtils.collapseTokens(stringLit, " "));
-
- return true;
- }
-
- private boolean processCommand(final String tk) {
- char[] comms = null;
-
- if (tk.length() > 5) {
- /* Pull off {@S and closing } */
- comms = tk.substring(3, tk.length() - 1).toCharArray();
- } else {
- /* Its a single char. command. */
- comms = new char[1];
- comms[0] = tk.charAt(3);
- }
-
- boolean succ;
-
- /* Process each command. */
- /*
- * @TODO 10/09/17 Ben Culkin :StreamCommands
- * This should probably be refactored in some way, so as to
- * make it easier to add new commands.
- */
- for (final char comm : comms) {
- switch (comm) {
- case '+':
- newStream();
- break;
- case '>':
- succ = rightStream();
- if (!succ) {
- return false;
- }
- break;
- case '<':
- succ = leftStream();
- if (!succ) {
- return false;
- }
- break;
- case '-':
- succ = deleteStream();
- if (!succ) {
- return false;
- }
- break;
- case 'M':
- succ = mergeStream();
- if (!succ) {
- return false;
- }
- break;
- case 'L':
- succ = scleng.runProgram(currStream.toArray(new String[0]));
- if (!succ) {
- return false;
- }
- break;
- default:
- Errors.inst.printError(EK_STRM_INVCOM, tk);
- return false;
- }
- }
-
- return true;
- }
-}
diff --git a/dice-lang/src/bjc/dicelang/util/ResourceLoader.java b/dice-lang/src/bjc/dicelang/util/ResourceLoader.java
deleted file mode 100644
index db5c6fc..0000000
--- a/dice-lang/src/bjc/dicelang/util/ResourceLoader.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package bjc.dicelang.util;
-
-import static bjc.dicelang.Errors.ErrorKey.EK_MISC_IOEX;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import bjc.dicelang.Errors;
-
-/**
- * Load resources bundled with DiceLang.
- *
- * @author EVE
- *
- */
-public class ResourceLoader {
- /**
- * Loads a .help file from the data/help directory.
- *
- * @param name
- * The name of the help file to load.
- *
- * @return The contents of the help file, or null if it could not be
- * opened.
- */
- public static String[] loadHelpFile(final String name) {
- final URL fle = ResourceLoader.class.getResource("/data/help/" + name + ".help");
-
- try {
- Path pth = Paths.get(fle.toURI());
-
- return Files.lines(pth).toArray(sze -> new String[sze]);
- } catch (IOException | URISyntaxException ioex) {
- Errors.inst.printError(EK_MISC_IOEX, fle.toString());
- }
-
- return null;
- }
-}