From f9d9bd4bbf7dd6a297e1daf5ee7b4263d706d9cd Mon Sep 17 00:00:00 2001 From: bjculkin Date: Thu, 1 Mar 2018 19:13:48 -0500 Subject: Update --- base/src/bjc/dicelang/CLIArgsParser.java | 208 ------------ base/src/bjc/dicelang/CompilerTweaker.java | 14 +- base/src/bjc/dicelang/Define.java | 46 +-- base/src/bjc/dicelang/DiceLangConsole.java | 312 ----------------- base/src/bjc/dicelang/DiceLangEngine.java | 172 +++++----- base/src/bjc/dicelang/DiceToken.java | 43 --- base/src/bjc/dicelang/Errors.java | 37 +- base/src/bjc/dicelang/FloatToken.java | 40 --- base/src/bjc/dicelang/Node.java | 9 +- base/src/bjc/dicelang/Parser.java | 44 +-- base/src/bjc/dicelang/Shunter.java | 106 +++--- base/src/bjc/dicelang/Token.java | 162 --------- base/src/bjc/dicelang/Tokenizer.java | 31 +- base/src/bjc/dicelang/cli/CLIArgsParser.java | 211 ++++++++++++ base/src/bjc/dicelang/cli/DiceLangConsole.java | 374 +++++++++++++++++++++ base/src/bjc/dicelang/cli/DiceLangPragma.java | 36 ++ .../src/bjc/dicelang/eval/DiceEvaluatorResult.java | 2 +- base/src/bjc/dicelang/eval/Evaluator.java | 184 +++++----- base/src/bjc/dicelang/eval/EvaluatorResult.java | 2 +- .../bjc/dicelang/eval/FailureEvaluatorResult.java | 23 +- .../bjc/dicelang/eval/FloatEvaluatorResult.java | 18 +- .../bjc/dicelang/eval/StringEvaluatorResult.java | 21 +- base/src/bjc/dicelang/expr/ExprREPL.java | 23 +- base/src/bjc/dicelang/expr/Ezpr.java | 38 ++- base/src/bjc/dicelang/expr/Lexer.java | 6 +- base/src/bjc/dicelang/expr/Parser.java | 14 +- base/src/bjc/dicelang/expr/Shunter.java | 34 +- base/src/bjc/dicelang/expr/Token.java | 10 +- base/src/bjc/dicelang/expr/TokenType.java | 4 +- base/src/bjc/dicelang/expr/Tokens.java | 8 +- base/src/bjc/dicelang/tokens/DiceToken.java | 38 +++ base/src/bjc/dicelang/tokens/FloatToken.java | 36 ++ base/src/bjc/dicelang/tokens/IntToken.java | 26 ++ base/src/bjc/dicelang/tokens/Token.java | 168 +++++++++ base/src/bjc/dicelang/util/ResourceLoader.java | 7 +- 35 files changed, 1332 insertions(+), 1175 deletions(-) delete mode 100644 base/src/bjc/dicelang/CLIArgsParser.java delete mode 100644 base/src/bjc/dicelang/DiceLangConsole.java delete mode 100644 base/src/bjc/dicelang/DiceToken.java delete mode 100644 base/src/bjc/dicelang/FloatToken.java delete mode 100644 base/src/bjc/dicelang/Token.java create mode 100644 base/src/bjc/dicelang/cli/CLIArgsParser.java create mode 100644 base/src/bjc/dicelang/cli/DiceLangConsole.java create mode 100644 base/src/bjc/dicelang/cli/DiceLangPragma.java create mode 100644 base/src/bjc/dicelang/tokens/DiceToken.java create mode 100644 base/src/bjc/dicelang/tokens/FloatToken.java create mode 100644 base/src/bjc/dicelang/tokens/IntToken.java create mode 100644 base/src/bjc/dicelang/tokens/Token.java (limited to 'base/src/bjc/dicelang') diff --git a/base/src/bjc/dicelang/CLIArgsParser.java b/base/src/bjc/dicelang/CLIArgsParser.java deleted file mode 100644 index 553692b..0000000 --- a/base/src/bjc/dicelang/CLIArgsParser.java +++ /dev/null @@ -1,208 +0,0 @@ -package bjc.dicelang; - -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; - -import static bjc.dicelang.Errors.ErrorKey.*; - -/** - * 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/base/src/bjc/dicelang/CompilerTweaker.java b/base/src/bjc/dicelang/CompilerTweaker.java index b11caa9..5f2b9f6 100644 --- a/base/src/bjc/dicelang/CompilerTweaker.java +++ b/base/src/bjc/dicelang/CompilerTweaker.java @@ -21,7 +21,7 @@ public class CompilerTweaker { * Create a new compiler tweaker. * * @param engine - * The engine to tweak. + * The engine to tweak. */ public CompilerTweaker(final DiceLangEngine engine) { eng = engine; @@ -33,7 +33,7 @@ public class CompilerTweaker { * Add a string literal to the compiler's internal banks. * * @param val - * The string literal to add. + * The string literal to add. * * @return The key into the string literal table for this string. */ @@ -48,7 +48,7 @@ public class CompilerTweaker { * Add a line defn to the compiler. * * @param dfn - * The defn to add. + * The defn to add. */ public void addLineDefine(final Define dfn) { eng.addLineDefine(dfn); @@ -58,7 +58,7 @@ public class CompilerTweaker { * Add a token defn to the compiler. * * @param dfn - * The defn to add. + * The defn to add. */ public void addTokenDefine(final Define dfn) { eng.addTokenDefine(dfn); @@ -68,7 +68,7 @@ public class CompilerTweaker { * Adds delimiters that are expanded from tokens. * * @param delims - * The delimiters to expand on. + * The delimiters to expand on. */ public void addDelimiter(final String... delims) { opExpander.addSimpleDelimiters(delims); @@ -78,7 +78,7 @@ public class CompilerTweaker { * Adds multi-character delimiters that are expanded from tokens. * * @param delims - * The multi-character delimiters to expand on. + * The multi-character delimiters to expand on. */ public void addMultiDelimiter(final String... delims) { opExpander.addMultiDelimiters(delims); @@ -95,7 +95,7 @@ public class CompilerTweaker { * Change the max no. of times defines are allowed to recur. * * @param times - * The number of times to allow defines to recur. + * The number of times to allow defines to recur. */ public static void setDefineRecurLimit(final int times) { Define.MAX_RECURS = times; diff --git a/base/src/bjc/dicelang/Define.java b/base/src/bjc/dicelang/Define.java index b11e10b..b0e8a21 100644 --- a/base/src/bjc/dicelang/Define.java +++ b/base/src/bjc/dicelang/Define.java @@ -63,25 +63,25 @@ public class Define implements UnaryOperator, Comparable { * Create a new define. * * @param priorty - * The priority of the define. + * The priority of the define. * * @param isSub - * Whether or not this is a 'sub-define' + * Whether or not this is a 'sub-define' * * @param recur - * Whether this define is recursive or not. + * Whether this define is recursive or not. * * @param isCircular - * Whether this define is circular or not. + * Whether this define is circular or not. * * @param predicte - * The string to use as a predicate. + * The string to use as a predicate. * * @param searchr - * The string to use as a search. + * The string to use as a search. * * @param replacrs - * The source for replacement strings. + * 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 replacrs) { @@ -90,10 +90,10 @@ public class Define implements UnaryOperator, Comparable { subType = isSub; /* Only try to compile non-null predicates */ - if (predicte != null) { + if(predicte != null) { try { predicate = Pattern.compile(predicte); - } catch (final PatternSyntaxException psex) { + } catch(final PatternSyntaxException psex) { Errors.inst.printError(EK_DFN_PREDSYN, psex.getMessage()); inError = true; return; @@ -103,7 +103,7 @@ public class Define implements UnaryOperator, Comparable { /* Compile the search pattern */ try { searcher = Pattern.compile(searchr); - } catch (final PatternSyntaxException psex) { + } catch(final PatternSyntaxException psex) { Errors.inst.printError(EK_DFN_SRCSYN, psex.getMessage()); inError = true; return; @@ -112,8 +112,8 @@ public class Define implements UnaryOperator, Comparable { inError = false; /* Check whether or not we do sub-replacements */ - if (subType) { - if (replacrs.iterator().hasNext()) { + if(subType) { + if(replacrs.iterator().hasNext()) { replacers = new CircularIterator<>(replacrs, isCircular); } else { replacers = null; @@ -121,7 +121,7 @@ public class Define implements UnaryOperator, Comparable { } else { final Iterator itr = replacrs.iterator(); - if (itr.hasNext()) { + if(itr.hasNext()) { replacer = itr.next(); } else { replacer = ""; @@ -131,22 +131,22 @@ public class Define implements UnaryOperator, Comparable { @Override public String apply(final String tok) { - if (inError) { + if(inError) { return tok; } - if (predicate != null) { - if (!predicate.matcher(tok).matches()) { + if(predicate != null) { + if(!predicate.matcher(tok).matches()) { return tok; } } String strang = doPass(tok); - if (doRecur) { + if(doRecur) { int recurCount = 0; - if (strang.equals(tok)) { + if(strang.equals(tok)) { return strang; } @@ -155,9 +155,9 @@ public class Define implements UnaryOperator, Comparable { do { strang = doPass(tok); recurCount += 1; - } while (!strang.equals(oldStrang) && recurCount < MAX_RECURS); + } while(!strang.equals(oldStrang) && recurCount < MAX_RECURS); - if (recurCount >= MAX_RECURS) { + if(recurCount >= MAX_RECURS) { Errors.inst.printError(EK_DFN_RECUR, Integer.toString(MAX_RECURS), tok, strang); return strang; } @@ -170,11 +170,11 @@ public class Define implements UnaryOperator, Comparable { private String doPass(final String tok) { final Matcher searcherMatcher = searcher.matcher(tok); - if (subType) { + if(subType) { final StringBuffer sb = new StringBuffer(); - while (searcherMatcher.find()) { - if (replacers == null) { + while(searcherMatcher.find()) { + if(replacers == null) { searcherMatcher.appendReplacement(sb, ""); } else { final String replac = replacers.next(); diff --git a/base/src/bjc/dicelang/DiceLangConsole.java b/base/src/bjc/dicelang/DiceLangConsole.java deleted file mode 100644 index a43c1da..0000000 --- a/base/src/bjc/dicelang/DiceLangConsole.java +++ /dev/null @@ -1,312 +0,0 @@ -package bjc.dicelang; - -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; - -import static bjc.dicelang.Errors.ErrorKey.*; - -/** - * 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 ..."); - 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 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/base/src/bjc/dicelang/DiceLangEngine.java b/base/src/bjc/dicelang/DiceLangEngine.java index f8fc5c6..2aafcd5 100644 --- a/base/src/bjc/dicelang/DiceLangEngine.java +++ b/base/src/bjc/dicelang/DiceLangEngine.java @@ -13,6 +13,7 @@ import bjc.dicelang.eval.Evaluator; import bjc.dicelang.eval.EvaluatorResult; import bjc.dicelang.eval.FailureEvaluatorResult; import bjc.dicelang.scl.StreamEngine; +import bjc.dicelang.tokens.Token; import bjc.utils.data.ITree; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.FunctionalMap; @@ -24,7 +25,7 @@ import bjc.utils.parserutils.TokenUtils; import bjc.utils.parserutils.splitter.ConfigurableTokenSplitter; import static bjc.dicelang.Errors.ErrorKey.*; -import static bjc.dicelang.Token.Type.*; +import static bjc.dicelang.tokens.Token.Type.*; /** * Implements the orchestration necessary for processing DiceLang commands. @@ -36,8 +37,9 @@ public class DiceLangEngine { 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. + * 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 */ @@ -144,7 +146,7 @@ public class DiceLangEngine { * Add a defn that's applied to lines. * * @param dfn - * The defn to add. + * The defn to add. */ public void addLineDefine(final Define dfn) { lineDefns.add(dfn); @@ -156,7 +158,7 @@ public class DiceLangEngine { * Add a defn that's applied to tokens. * * @param dfn - * The defn to add. + * The defn to add. */ public void addTokenDefine(final Define dfn) { tokenDefns.add(dfn); @@ -215,7 +217,7 @@ public class DiceLangEngine { * Run a command to completion. * * @param command - * The command to run + * The command to run * * @return Whether or not the command ran successfully */ @@ -224,18 +226,19 @@ public class DiceLangEngine { /* * @NOTE * - * Instead of strings, this should maybe use a RawToken class or something. + * Instead of strings, this should maybe use a RawToken class or + * something. */ final IList preprocessedTokens = preprocessCommand(command); - if (preprocessedTokens == null) { + if(preprocessedTokens == null) { return false; } /* Lex the string tokens into token-tokens */ final IList lexedTokens = lexTokens(preprocessedTokens); - if (lexedTokens == null) { + if(lexedTokens == null) { return false; } @@ -243,7 +246,7 @@ public class DiceLangEngine { final IList> astForest = new FunctionalList<>(); final boolean succ = Parser.parseTokens(lexedTokens, astForest); - if (!succ) { + if(!succ) { return false; } @@ -256,14 +259,14 @@ public class DiceLangEngine { private IList lexTokens(final IList preprocessedTokens) { final IList lexedTokens = new FunctionalList<>(); - for (final String token : preprocessedTokens) { + for(final String token : preprocessedTokens) { String newTok = token; /* Apply token defns */ - for (final Define dfn : tokenDefns.toIterable()) { + for(final Define dfn : tokenDefns.toIterable()) { /* - * @NOTE What happens with a define that produces multiple tokens from one - * token? + * @NOTE What happens with a define that + * produces multiple tokens from one token? */ newTok = dfn.apply(newTok); } @@ -271,14 +274,14 @@ public class DiceLangEngine { /* Lex the token */ final Token tk = tokenzer.lexToken(token, stringLiterals); - if (debugMode) { + if(debugMode) { LOG.finer(String.format("lexed token: %s\n", tk)); } - if (tk == null) { + if(tk == null) { /* Ignore blank tokens */ continue; - } else if (tk == Token.NIL_TOKEN) { + } else if(tk == Token.NIL_TOKEN) { /* Fail on bad tokens */ return null; } else { @@ -286,7 +289,7 @@ public class DiceLangEngine { } } - if (debugMode) { + if(debugMode) { String msg = String.format("\tCommand after tokenization: %s\n", lexedTokens.toString()); LOG.fine(msg); System.out.print(msg); @@ -298,35 +301,37 @@ public class DiceLangEngine { boolean succ = removePreshuntTokens(lexedTokens, preparedTokens); - if (!succ) { + if(!succ) { return null; } - if (debugMode && !postfixMode) { - String msg = String.format("\tCommand after pre-shunter removal: %s\n", preparedTokens.toString()); + 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) { + if(!postfixMode && !prefixMode) { /* Shunt the tokens */ shuntedTokens = new FunctionalList<>(); succ = shunt.shuntTokens(preparedTokens, shuntedTokens); - if (!succ) { + if(!succ) { return null; } - } else if (prefixMode) { + } else if(prefixMode) { /* Reverse directional tokens */ /* - * @NOTE Merge these two operations into one iteration over the list? + * @NOTE Merge these two operations into one iteration + * over the list? */ preparedTokens.reverse(); shuntedTokens = preparedTokens.map(this::reverseToken); } - if (debugMode && !postfixMode) { + if(debugMode && !postfixMode) { String msg = String.format("\tCommand after shunting: %s\n", shuntedTokens.toString()); LOG.fine(msg); System.out.print(msg); @@ -334,7 +339,8 @@ public class DiceLangEngine { /* Expand token groups */ final IList readyTokens = shuntedTokens.flatMap(tk -> { - if (tk.type == Token.Type.TOKGROUP || tk.type == Token.Type.TAGOP || tk.type == Token.Type.TAGOPR) { + if(tk.type == Token.Type.TOKGROUP || tk.type == Token.Type.TAGOP + || tk.type == Token.Type.TAGOPR) { LOG.finer(String.format("Expanding token group to: %s\n", tk.tokenValues.toString())); return tk.tokenValues; } else { @@ -342,7 +348,7 @@ public class DiceLangEngine { } }); - if (debugMode && !postfixMode) { + if(debugMode && !postfixMode) { String msg = String.format("\tCommand after re-preshunting: %s\n", readyTokens.toString()); LOG.fine(msg); System.out.print(msg); @@ -357,7 +363,7 @@ public class DiceLangEngine { * These are things like (, {, and [ */ private Token reverseToken(final Token tk) { - switch (tk.type) { + switch(tk.type) { case OBRACE: return new Token(CBRACE, tk.intValue); case OPAREN: @@ -378,7 +384,7 @@ public class DiceLangEngine { /* Preprocess a command into a list of string tokens. */ private IList preprocessCommand(final String command) { /* Sort the defines if they aren't sorted */ - if (!defnsSorted) { + if(!defnsSorted) { sortDefns(); } @@ -386,24 +392,24 @@ public class DiceLangEngine { final IList streamToks = new FunctionalList<>(); final boolean succ = streamEng.doStreams(command.split(" "), streamToks); - if (!succ) { + if(!succ) { return null; } String newComm = ListUtils.collapseTokens(streamToks, " "); - if (debugMode) { + 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()) { + for(final Define dfn : lineDefns.toIterable()) { newComm = dfn.apply(newComm); } - if (debugMode) { + if(debugMode) { String msg = String.format("\tCommand after line defines: %s\n", newComm); LOG.fine(msg); System.out.print(msg); @@ -413,21 +419,23 @@ public class DiceLangEngine { final List destringedParts = TokenUtils.removeDQuotedStrings(newComm); final StringBuffer destringedCommand = new StringBuffer(); - for (final String part : destringedParts) { + for(final String part : destringedParts) { /* Handle string literals */ - if (part.startsWith("\"") && part.endsWith("\"")) { + 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. + * 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)); + if(debugMode) + LOG.finer(String.format("Replaced string literal '%s' with literal no. %d", + descVal, nextLiteral)); nextLiteral += 1; @@ -438,13 +446,13 @@ public class DiceLangEngine { } } - if (debugMode) { + 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) { + if(stringLiterals.size() > 0) { System.out.println("\tString literals in table"); stringLiterals.forEach((key, val) -> { @@ -462,18 +470,19 @@ public class DiceLangEngine { tokens = tokens.map(tk -> { final Matcher nonExpandMatcher = nonExpandPattern.matcher(tk); - if (nonExpandMatcher.matches()) { + 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)); + LOG.finer(String.format("Pulled non-expander '%s' to '%s'", nonExpandMatcher.group(1), + tkName)); return tkName; } return tk; }); - if (debugMode) { + if(debugMode) { String msg = String.format("\tCommand after removal of non-expanders: %s\n", tokens.toString()); LOG.fine(msg); System.out.print(msg); @@ -482,21 +491,21 @@ public class DiceLangEngine { /* Expand tokens */ IList fullyExpandedTokens = tokens.flatMap(opExpander::split); - if (debugMode) { - String msg = String.format("\tCommand after token expansion: %s\n", fullyExpandedTokens.toString()); + if(debugMode) { + String msg = String.format("\tCommand after token expansion: %s\n", + fullyExpandedTokens.toString()); LOG.fine(msg); System.out.print(msg); } /* Reinsert non-expanded tokens */ fullyExpandedTokens = fullyExpandedTokens.map(tk -> { - if (tk.startsWith("nonExpandToken")) - return nonExpandedTokens.get(tk); + if(tk.startsWith("nonExpandToken")) return nonExpandedTokens.get(tk); return tk; }); - if (debugMode) { + if(debugMode) { String msg = String.format("\tCommand after non-expander reinsertion: %s\n", fullyExpandedTokens.toString()); LOG.fine(msg); @@ -510,25 +519,26 @@ public class DiceLangEngine { private void evaluateForest(final IList> astForest) { int treeNo = 1; - for (final ITree ast : astForest) { - if (debugMode) { + for(final ITree ast : astForest) { + if(debugMode) { System.out.printf("\t\tTree %d in forest:\n%s\n", treeNo, ast.toString()); } - if (debugMode && stepEval) { + if(debugMode && stepEval) { /* - * @NOTE This is broken until stepwise top-down tree transforms are fixed. + * @NOTE This is broken until stepwise top-down + * tree transforms are fixed. */ int step = 1; /* Evaluate it step by step */ - for (final Iterator> itr = eval.stepDebug(ast); itr.hasNext();) { + for(final Iterator> itr = eval.stepDebug(ast); itr.hasNext();) { final ITree nodeStep = itr.next(); System.out.printf("\t\tStep %d: Node is %s", step, nodeStep); /* Don't evaluate null steps */ - if (nodeStep == null) { + if(nodeStep == null) { System.out.println(); step += 1; @@ -536,18 +546,18 @@ public class DiceLangEngine { } /* Print out details for results */ - if (nodeStep.getHead().type == Node.Type.RESULT) { + 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) { + if(res.type == EvaluatorResult.Type.DICE) { String value = ((DiceEvaluatorResult) res).diceVal.value(); System.out.printf(" (sample roll %s)", value); } - if (res.type == EvaluatorResult.Type.FAILURE) { + if(res.type == EvaluatorResult.Type.FAILURE) { ITree otree = ((FailureEvaluatorResult) res).origVal; System.out.printf(" (original tree is %s)", otree); @@ -564,10 +574,10 @@ public class DiceLangEngine { /* Evaluate it normally */ final EvaluatorResult res = eval.evaluate(ast); - if (debugMode) { + if(debugMode) { System.out.printf("\t\tEvaluates to %s", res); - if (res.type == EvaluatorResult.Type.DICE) { + if(res.type == EvaluatorResult.Type.DICE) { String value = ((DiceEvaluatorResult) res).diceVal.value(); System.out.println("\t\t (sample roll " + value + ")"); @@ -590,24 +600,26 @@ public class DiceLangEngine { final Deque> bracedTokens = new LinkedList<>(); IList curBracedTokens = new FunctionalList<>(); - for (final Token tk : lexedTokens) { - if (tk.type == Token.Type.OBRACE && tk.intValue == 2) { + for(final Token tk : lexedTokens) { + if(tk.type == Token.Type.OBRACE && tk.intValue == 2) { /* Open a preshunt group. */ curBraceCount += 1; - if (curBraceCount != 1) { + if(curBraceCount != 1) { /* - * Push the old group onto the group stack. + * Push the old group onto the group + * stack. */ bracedTokens.push(curBracedTokens); } curBracedTokens = new FunctionalList<>(); - } else if (tk.type == Token.Type.CBRACE && tk.intValue == 2) { + } else if(tk.type == Token.Type.CBRACE && tk.intValue == 2) { /* Close a preshunt group. */ - if (curBraceCount == 0) { + if(curBraceCount == 0) { /* - * Error if there couldn't have been an opening. + * Error if there couldn't have been an + * opening. */ Errors.inst.printError(EK_ENG_NOOPENING); return false; @@ -620,32 +632,36 @@ public class DiceLangEngine { /* Shunt preshunt group. */ final boolean success = shunt.shuntTokens(curBracedTokens, preshuntTokens); - if (debugMode) { - System.out.println("\t\tPreshunted " + curBracedTokens + " into " + preshuntTokens); + if(debugMode) { + System.out.println("\t\tPreshunted " + curBracedTokens + " into " + + preshuntTokens); } - if (!success) { + if(!success) { return false; } - if (curBraceCount >= 1) { + if(curBraceCount >= 1) { /* - * Add the preshunt group to the previous group. + * 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. + * 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.. + * Add the token to the active preshunt group, + * if there is one.. */ - if (curBraceCount >= 1) { + if(curBraceCount >= 1) { curBracedTokens.add(tk); } else { preparedTokens.add(tk); @@ -653,7 +669,7 @@ public class DiceLangEngine { } } - if (curBraceCount > 0) { + if(curBraceCount > 0) { /* There was an unclosed group. */ Errors.inst.printError(EK_ENG_NOCLOSING); return false; @@ -671,8 +687,8 @@ public class DiceLangEngine { /* * @NOTE * - * The string literal table should be abstracted into some kind of auto-numbered - * map thing. + * 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/base/src/bjc/dicelang/DiceToken.java b/base/src/bjc/dicelang/DiceToken.java deleted file mode 100644 index fcb8a0c..0000000 --- a/base/src/bjc/dicelang/DiceToken.java +++ /dev/null @@ -1,43 +0,0 @@ -package bjc.dicelang; - -import bjc.dicelang.dice.DiceExpression; - -public class DiceToken extends Token { - public DiceExpression diceValue; - - public DiceToken(DiceExpression val) { - super(Type.DICE_LIT); - - diceValue = val; - } - - @Override - public String toString() { - return super.toString() + "(" + diceValue + ")"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((diceValue == null) ? 0 : diceValue.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - DiceToken other = (DiceToken) obj; - if (diceValue == null) { - if (other.diceValue != null) - return false; - } else if (!diceValue.equals(other.diceValue)) - return false; - return true; - } -} diff --git a/base/src/bjc/dicelang/Errors.java b/base/src/bjc/dicelang/Errors.java index 2577a32..8d3c969 100644 --- a/base/src/bjc/dicelang/Errors.java +++ b/base/src/bjc/dicelang/Errors.java @@ -273,15 +273,15 @@ public class Errors { * Print an error. * * @param key - * The key of the error. + * The key of the error. * * @param args - * The arguments for the error. + * The arguments for the error. */ public void printError(final ErrorKey key, final String... args) { - switch (mode) { + switch(mode) { case WIZARD: - if (key == ErrorKey.EK_MISC_NOFILE) { + if(key == ErrorKey.EK_MISC_NOFILE) { System.out.println("\t? 404"); } else { System.out.println("\t? " + key.ordinal()); @@ -299,7 +299,7 @@ public class Errors { } private static void devError(final ErrorKey key, final String[] args) { - switch (key) { + switch(key) { case EK_DFN_PREDSYN: System.out.printf("\tERROR: Incorrect define guard syntax %s\n", args[0]); break; @@ -309,8 +309,10 @@ public class Errors { 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]); + 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: @@ -322,7 +324,8 @@ public class Errors { break; case EK_ENG_NOOPENING: - System.out.printf("\tERROR: Encountered closing doublebrace without" + " matching opening doublebrace\n"); + System.out.printf("\tERROR: Encountered closing doublebrace without" + + " matching opening doublebrace\n"); break; case EK_ENG_NOCLOSING: @@ -346,8 +349,8 @@ public class Errors { 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]); + 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: @@ -383,7 +386,8 @@ public class Errors { break; case EK_EVAL_INVDGROUP: - System.out.printf("\tERROR: Dice group operator expects scalar dice or integers," + " not %s\n", args[0]); + System.out.printf("\tERROR: Dice group operator expects scalar dice or integers," + " not %s\n", + args[0]); break; case EK_EVAL_INVDICE: @@ -407,8 +411,8 @@ public class Errors { break; case EK_PARSE_UNCLOSE: - System.out.printf("\tERROR: Found group closer without opener: (closing was %s" + ", expected %s)\n", - args[0], args[1]); + System.out.printf("\tERROR: Found group closer without opener: (closing was %s" + + ", expected %s)\n", args[0], args[1]); break; case EK_PARSE_BINARY: @@ -434,12 +438,13 @@ public class Errors { 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]); + 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]); + System.out.printf("\tERROR: Couldn't find matching grouping %s (expected %s)\n", args[0], + args[1]); break; case EK_SHUNT_NOTASSOC: diff --git a/base/src/bjc/dicelang/FloatToken.java b/base/src/bjc/dicelang/FloatToken.java deleted file mode 100644 index 786df6e..0000000 --- a/base/src/bjc/dicelang/FloatToken.java +++ /dev/null @@ -1,40 +0,0 @@ -package bjc.dicelang; - -public class FloatToken extends Token { - public double floatValue; - - public FloatToken(double val) { - super(Type.FLOAT_LIT); - - floatValue = val; - } - - @Override - public String toString() { - return super.toString() + "(" + floatValue + ")"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - long temp; - temp = Double.doubleToLongBits(floatValue); - result = prime * result + (int) (temp ^ (temp >>> 32)); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - FloatToken other = (FloatToken) obj; - if (Double.doubleToLongBits(floatValue) != Double.doubleToLongBits(other.floatValue)) - return false; - return true; - } -} diff --git a/base/src/bjc/dicelang/Node.java b/base/src/bjc/dicelang/Node.java index 7e97f9c..a9e14db 100644 --- a/base/src/bjc/dicelang/Node.java +++ b/base/src/bjc/dicelang/Node.java @@ -2,6 +2,7 @@ package bjc.dicelang; import bjc.dicelang.eval.EvaluatorResult; import bjc.dicelang.eval.FailureEvaluatorResult; +import bjc.dicelang.tokens.Token; import bjc.utils.data.ITree; /* @@ -62,7 +63,7 @@ public class Node { @Override public String toString() { - switch (type) { + switch(type) { case UNARYOP: case BINOP: return "(" + type.name() + " : " + operatorType + ")"; @@ -84,17 +85,17 @@ public class Node { @Override public boolean equals(final Object other) { - if (!(other instanceof Node)) { + if(!(other instanceof Node)) { return false; } final Node otk = (Node) other; - if (otk.type != type) { + if(otk.type != type) { return false; } - switch (type) { + switch(type) { case OGROUP: return tokenVal.equals(otk.tokenVal); diff --git a/base/src/bjc/dicelang/Parser.java b/base/src/bjc/dicelang/Parser.java index 76730b9..ffbfb9d 100644 --- a/base/src/bjc/dicelang/Parser.java +++ b/base/src/bjc/dicelang/Parser.java @@ -10,12 +10,13 @@ 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 static bjc.dicelang.tokens.Token.Type.CBRACE; +import static bjc.dicelang.tokens.Token.Type.CBRACKET; import java.util.Deque; import java.util.LinkedList; +import bjc.dicelang.tokens.Token; import bjc.utils.data.ITree; import bjc.utils.data.Tree; import bjc.utils.funcdata.IList; @@ -36,18 +37,18 @@ public class Parser { * Parse a series of tokens to a forest of ASTs. * * @param tokens - * The list of tokens to parse. + * The list of tokens to parse. * * @param results - * The place to set results. + * The place to set results. * * @return Whether or not the parse was successful. */ public static boolean parseTokens(final IList tokens, final IList> results) { final Deque> working = new LinkedList<>(); - for (final Token tk : tokens) { - switch (tk.type) { + for(final Token tk : tokens) { + switch(tk.type) { case OBRACKET: case OBRACE: /* Parse opening delims. */ @@ -59,7 +60,7 @@ public class Parser { /* Parse closing delims. */ final boolean sc = parseClosingGrouper(working, tk); - if (!sc) { + if(!sc) { return false; } @@ -75,7 +76,7 @@ public class Parser { case LET: case BIND: /* Parse binary operator. */ - if (working.size() < 2) { + if(working.size() < 2) { Errors.inst.printError(EK_PARSE_BINARY); return false; } @@ -85,10 +86,10 @@ public class Parser { case ADD: case SUBTRACT: /* Handle binary/unary operators. */ - if (working.size() == 0) { + if(working.size() == 0) { Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString()); return false; - } else if (working.size() == 1) { + } else if(working.size() == 1) { final ITree operand = working.pop(); final ITree opNode = new Tree<>(new Node(UNARYOP, tk.type)); @@ -104,7 +105,7 @@ public class Parser { case DICESCALAR: case DICEFUDGE: /* Handle unary operators. */ - if (working.size() == 0) { + if(working.size() == 0) { Errors.inst.printError(EK_PARSE_UNOPERAND, tk.toString()); } else { final ITree operand = working.pop(); @@ -131,9 +132,10 @@ public class Parser { } /* - * Collect the remaining nodes as the roots of the trees in the AST forest. + * Collect the remaining nodes as the roots of the trees in the + * AST forest. */ - for (final ITree ast : working) { + for(final ITree ast : working) { results.add(ast); } @@ -155,14 +157,14 @@ public class Parser { /* Parse a closing delimiter. */ private static boolean parseClosingGrouper(final Deque> working, final Token tk) { - if (working.size() == 0) { + if(working.size() == 0) { Errors.inst.printError(EK_PARSE_NOCLOSE); return false; } ITree groupNode = null; - switch (tk.type) { + switch(tk.type) { case CBRACE: groupNode = new Tree<>(new Node(GROUP, Node.GroupType.CODE)); break; @@ -176,22 +178,22 @@ public class Parser { Token matching = null; - if (tk.type == CBRACKET) { + if(tk.type == CBRACKET) { matching = new Token(Token.Type.OBRACKET, tk.intValue); - } else if (tk.type == CBRACE) { + } else if(tk.type == CBRACE) { matching = new Token(Token.Type.OBRACE, tk.intValue); } final ITree matchNode = new Tree<>(new Node(OGROUP, matching)); - if (!working.contains(matchNode)) { + 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 ast : working) { + for(final ITree ast : working) { System.out.println("Tree " + treeNo++ + ": " + ast.toString()); } @@ -200,14 +202,14 @@ public class Parser { final Deque> childs = new LinkedList<>(); - while (!working.peek().equals(matchNode)) { + while(!working.peek().equals(matchNode)) { childs.push(working.pop()); } /* Discard opener */ working.pop(); - for (final ITree child : childs) { + for(final ITree child : childs) { groupNode.addChild(child); } diff --git a/base/src/bjc/dicelang/Shunter.java b/base/src/bjc/dicelang/Shunter.java index 01029cd..79ab97a 100644 --- a/base/src/bjc/dicelang/Shunter.java +++ b/base/src/bjc/dicelang/Shunter.java @@ -5,6 +5,7 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.Set; +import bjc.dicelang.tokens.Token; import bjc.utils.funcdata.FunctionalList; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.IList; @@ -15,7 +16,7 @@ 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.*; +import static bjc.dicelang.tokens.Token.Type.*; /** * Shunt a set of infix tokens to postfix tokens. @@ -34,8 +35,8 @@ public class Shunter { Set notAssoc; /* - * Unary operators that can only be applied to non-operator tokens and yield - * operator tokens. + * Unary operators that can only be applied to non-operator tokens and + * yield operator tokens. */ Set unaryAdjectives; @@ -46,8 +47,8 @@ public class Shunter { Set unaryAdverbs; /* - * Unary operators that can only be applied to operator tokens and yield data - * tokens + * Unary operators that can only be applied to operator tokens and yield + * data tokens */ Set unaryGerunds; @@ -108,10 +109,10 @@ public class Shunter { * Shunt a set of tokens from infix to postfix. * * @param tks - * The tokens to input. + * The tokens to input. * * @param returned - * The postfix tokens. + * The postfix tokens. * * @return Whether or not the shunt succeeded. */ @@ -126,32 +127,32 @@ public class Shunter { /* Tokens to feed ahead of the current one. */ final Deque feed = new LinkedList<>(); - for (final Token tk : tks.toIterable()) { + for(final Token tk : tks.toIterable()) { boolean succ; /* Drain the feed queue. */ - while (feed.size() != 0) { + while(feed.size() != 0) { succ = shuntToken(feed.poll(), opStack, unaryOps, currReturned, feed); - if (!succ) { + if(!succ) { return false; } } succ = shuntToken(tk, opStack, unaryOps, currReturned, feed); - if (!succ) { + if(!succ) { return false; } } /* Flush leftover operators. */ - while (!opStack.isEmpty()) { + while(!opStack.isEmpty()) { currReturned.addLast(opStack.pop()); } /* Add the tokens to the returned list. */ - for (final Token tk : currReturned) { + for(final Token tk : currReturned) { returned.add(tk); } @@ -162,8 +163,8 @@ public class Shunter { private boolean shuntToken(final Token tk, final Deque opStack, final Deque unaryStack, final Deque currReturned, final Deque feed) { /* Handle unary operators. */ - if (unaryStack.size() != 0) { - if (isUnary(tk)) { + if(unaryStack.size() != 0) { + if(isUnary(tk)) { unaryStack.add(tk); return true; } @@ -172,18 +173,19 @@ public class Shunter { final Token.Type unaryType = unaryOp.type; - if (unaryAdjectives.contains(unaryType)) { + if(unaryAdjectives.contains(unaryType)) { /* - * Handle unary adjectives that take a non-operator. + * Handle unary adjectives that take a + * non-operator. */ - if (isOp(tk)) { + 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) { + if(tk.type == TAGOP) { newTok.tokenValues = tk.tokenValues; } else { newTok.tokenValues = new FunctionalList<>(tk); @@ -193,16 +195,18 @@ public class Shunter { opStack.push(newTok); return true; - } else if (unaryAdverbs.contains(unaryType)) { - /* Handle unary adverbs that take an operator. */ - if (!isOp(tk)) { + } 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) { + if(tk.type == TAGOP) { newTok.tokenValues = tk.tokenValues; } else { newTok.tokenValues = new FunctionalList<>(tk); @@ -215,15 +219,15 @@ public class Shunter { } } - if (isUnary(tk)) { + if(isUnary(tk)) { unaryStack.add(tk); return true; - } else if (isOp(tk)) { + } else if(isOp(tk)) { /* Drain higher precedence operators. */ - while (!opStack.isEmpty() && isHigherPrec(tk, opStack.peek())) { + while(!opStack.isEmpty() && isHigherPrec(tk, opStack.peek())) { final Token newOp = opStack.pop(); - if (tk.type == newOp.type && notAssoc.contains(tk.type)) { + if(tk.type == newOp.type && notAssoc.contains(tk.type)) { Errors.inst.printError(EK_SHUNT_NOTASSOC, tk.type.toString()); } @@ -231,17 +235,17 @@ public class Shunter { } opStack.push(tk); - } else if (tk.type == OPAREN || tk.type == OBRACE) { + } else if(tk.type == OPAREN || tk.type == OBRACE) { opStack.push(tk); - if (tk.type == OBRACE) { + if(tk.type == OBRACE) { currReturned.addLast(tk); } - } else if (tk.type == CPAREN || tk.type == CBRACE) { + } else if(tk.type == CPAREN || tk.type == CBRACE) { /* Handle closing delimiter. */ Token matching = null; - switch (tk.type) { + switch(tk.type) { case CPAREN: matching = new Token(OPAREN, tk.intValue); break; @@ -253,33 +257,33 @@ public class Shunter { return false; } - if (!opStack.contains(matching)) { + if(!opStack.contains(matching)) { Errors.inst.printError(EK_SHUNT_NOGROUP, tk.toString(), matching.toString()); return false; } - while (!opStack.peek().equals(matching)) { + while(!opStack.peek().equals(matching)) { currReturned.addLast(opStack.pop()); } - if (tk.type == CBRACE) { + if(tk.type == CBRACE) { currReturned.addLast(tk); } opStack.pop(); - } else if (tk.type == GROUPSEP) { + } else if(tk.type == GROUPSEP) { /* Add a grouped token. */ final IList group = new FunctionalList<>(); - while (currReturned.size() != 0 && !currReturned.peek().isGrouper()) { + while(currReturned.size() != 0 && !currReturned.peek().isGrouper()) { group.add(currReturned.pop()); } - while (opStack.size() != 0 && !opStack.peek().isGrouper()) { + while(opStack.size() != 0 && !opStack.peek().isGrouper()) { group.add(opStack.pop()); } - if (currReturned.size() == 0) { + if(currReturned.size() == 0) { Errors.inst.printError(EK_SHUNT_INVSEP); return false; } @@ -299,31 +303,31 @@ public class Shunter { boolean exists = ops.containsKey(right); - if (rght.type == TAGOPR) { + if(rght.type == TAGOPR) { exists = true; } /* If it doesn't, the left is higher precedence. */ - if (!exists) { + if(!exists) { return false; } int rightPrecedence; int leftPrecedence; - if (rght.type == TAGOPR) { + if(rght.type == TAGOPR) { rightPrecedence = (int) rght.intValue; } else { rightPrecedence = ops.get(right); } - if (lft.type == TAGOPR) { + if(lft.type == TAGOPR) { leftPrecedence = (int) lft.intValue; } else { leftPrecedence = ops.get(left); } - if (rightAssoc.contains(left)) { + if(rightAssoc.contains(left)) { return rightPrecedence > leftPrecedence; } @@ -334,23 +338,23 @@ public class Shunter { private boolean isOp(final Token tk) { final Token.Type ty = tk.type; - if (ops.containsKey(ty)) { + if(ops.containsKey(ty)) { return true; } - if (unaryAdjectives.contains(ty)) { + if(unaryAdjectives.contains(ty)) { return true; } - if (unaryAdverbs.contains(ty)) { + if(unaryAdverbs.contains(ty)) { return true; } - if (unaryGerunds.contains(ty)) { + if(unaryGerunds.contains(ty)) { return true; } - if (ty == TAGOPR) { + if(ty == TAGOPR) { return true; } @@ -361,15 +365,15 @@ public class Shunter { private boolean isUnary(final Token tk) { final Token.Type ty = tk.type; - if (unaryAdjectives.contains(ty)) { + if(unaryAdjectives.contains(ty)) { return true; } - if (unaryAdverbs.contains(ty)) { + if(unaryAdverbs.contains(ty)) { return true; } - if (unaryGerunds.contains(ty)) { + if(unaryGerunds.contains(ty)) { return true; } diff --git a/base/src/bjc/dicelang/Token.java b/base/src/bjc/dicelang/Token.java deleted file mode 100644 index b940925..0000000 --- a/base/src/bjc/dicelang/Token.java +++ /dev/null @@ -1,162 +0,0 @@ -package bjc.dicelang; - -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. - */ - /* - * Math tokens. - */ - ADD, SUBTRACT, MULTIPLY, DIVIDE, IDIVIDE, - - /* - * Literal tokens. - */ - INT_LIT, FLOAT_LIT, STRING_LIT, VREF, DICE_LIT, - - /* - * Dice operators. - */ - DICESCALAR, DICEFUDGE, DICEGROUP, DICECONCAT, DICELIST, - - /* - * Expression operators. - */ - LET, BIND, COERCE, - - /* - * String operators. - */ - STRCAT, STRREP, - - /* - * Grouping operators. - */ - 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 - * - * - TOKGROUP (the tokens in the group) - * - * - TAG* (the tagged construct) - * - */ - public IList 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 IList 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 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; - } - } -} diff --git a/base/src/bjc/dicelang/Tokenizer.java b/base/src/bjc/dicelang/Tokenizer.java index 3a6db22..cd732ee 100644 --- a/base/src/bjc/dicelang/Tokenizer.java +++ b/base/src/bjc/dicelang/Tokenizer.java @@ -4,13 +4,16 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import bjc.dicelang.dice.DiceBox; +import bjc.dicelang.tokens.DiceToken; +import bjc.dicelang.tokens.FloatToken; +import bjc.dicelang.tokens.Token; import bjc.utils.funcdata.FunctionalMap; import bjc.utils.funcdata.IMap; import bjc.utils.funcutils.StringUtils; import bjc.utils.parserutils.TokenUtils; import static bjc.dicelang.Errors.ErrorKey.*; -import static bjc.dicelang.Token.Type.*; +import static bjc.dicelang.tokens.Token.Type.*; /** * Converts strings into tokens. @@ -49,16 +52,16 @@ public class Tokenizer { } public Token lexToken(final String token, final IMap stringLts) { - if (token.equals("")) { + if(token.equals("")) { return null; } Token tk = Token.NIL_TOKEN; - if (litTokens.containsKey(token)) { + if(litTokens.containsKey(token)) { tk = new Token(litTokens.get(token)); } else { - switch (token.charAt(0)) { + switch(token.charAt(0)) { case '(': case ')': case '[': @@ -78,9 +81,9 @@ public class Tokenizer { private static Token tokenizeGrouping(final String token) { Token tk = Token.NIL_TOKEN; - if (StringUtils.containsOnly(token, "\\" + token.charAt(0))) { + if(StringUtils.containsOnly(token, "\\" + token.charAt(0))) { /* Handle multiple-grouped delimiters. */ - switch (token.charAt(0)) { + switch(token.charAt(0)) { case '(': tk = new Token(OPAREN, token.length()); break; @@ -125,15 +128,15 @@ public class Tokenizer { String token = rtoken.trim(); - if (TokenUtils.isInt(token)) { + if(TokenUtils.isInt(token)) { tk = new Token(INT_LIT, Long.parseLong(token)); - } else if (hexadecimalMatcher.matcher(token).matches()) { + } 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()) { + } 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) { + if(parseBase < Character.MIN_RADIX || parseBase > Character.MAX_RADIX) { Errors.inst.printError(EK_TOK_INVBASE, Integer.toString(parseBase)); return Token.NIL_TOKEN; } @@ -142,18 +145,18 @@ public class Tokenizer { try { tk = new Token(INT_LIT, Long.parseLong(flexNum, parseBase)); - } catch (final NumberFormatException nfex) { + } catch(final NumberFormatException nfex) { Errors.inst.printError(EK_TOK_INVFLEX, flexNum, Integer.toString(parseBase)); return Token.NIL_TOKEN; } - } else if (TokenUtils.isDouble(token)) { + } else if(TokenUtils.isDouble(token)) { tk = new FloatToken(Double.parseDouble(token)); - } else if (DiceBox.isValidExpression(token)) { + } else if(DiceBox.isValidExpression(token)) { tk = new DiceToken(DiceBox.parseExpression(token)); } else { final Matcher stringLit = stringLitMatcher.matcher(token); - if (stringLit.matches()) { + if(stringLit.matches()) { final int litNum = Integer.parseInt(stringLit.group(1)); eng.addStringLiteral(litNum, stringLts.get(token)); diff --git a/base/src/bjc/dicelang/cli/CLIArgsParser.java b/base/src/bjc/dicelang/cli/CLIArgsParser.java new file mode 100644 index 0000000..b4c0c7c --- /dev/null +++ b/base/src/bjc/dicelang/cli/CLIArgsParser.java @@ -0,0 +1,211 @@ +package bjc.dicelang.cli; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Arrays; +import java.util.Scanner; + +import bjc.dicelang.Define; +import bjc.dicelang.DiceLangEngine; +import bjc.dicelang.Errors; +import bjc.dicelang.util.ResourceLoader; + +import static bjc.dicelang.Errors.ErrorKey.*; + +/** + * 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/base/src/bjc/dicelang/cli/DiceLangConsole.java b/base/src/bjc/dicelang/cli/DiceLangConsole.java new file mode 100644 index 0000000..c19793f --- /dev/null +++ b/base/src/bjc/dicelang/cli/DiceLangConsole.java @@ -0,0 +1,374 @@ +package bjc.dicelang.cli; + +import bjc.dicelang.Define; +import bjc.dicelang.DiceLangEngine; +import bjc.dicelang.Errors; +import bjc.dicelang.Define.Type; +import bjc.utils.funcdata.FunctionalMap; +import bjc.utils.funcdata.IMap; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.function.BiPredicate; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jline.ConsoleReader; +import jline.Terminal; + +import static bjc.dicelang.Errors.ErrorKey.*; + +/** + * 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; + + /* Are we in multi-line mode? */ + private boolean multiLine; + + private static IMap pragmas; + + static { + pragmas = new FunctionalMap<>(); + + pragmas.put("debug", new DiceLangPragma() { + + @Override + public String getDescription() { + return "Toggle debug mode, which includes a bunch more output during various stages of compilation and interpretation"; + } + + @Override + public String getBrief() { + return "Toggle Debug mode"; + } + + @Override + public boolean execute(String lne, DiceLangEngine eng) { + System.out.println("\tDebug mode is now " + eng.toggleDebug()); + return true; + } + }); + } + + /** + * 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"); + + do { + 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. */ + if(comm.equals("quit") || comm.equals("exit")) { + break; + } + + 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 { + if(multiLine) { + try { + do { + String nLine = read.readLine( + String.format("(%d)\t...> ", commandNumber)); + + if(nLine.trim().equals("")) break; + + comm = String.format("%s %s", comm, nLine); + } while(true); + } catch(IOException ioex) { + System.out.println("ERROR: I/O failed"); + return; + } + } + /* 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; + } + } while(true); + + } + + /* 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)); + case "multi-line": + multiLine = !multiLine; + break; + 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 ..."); + break; + case "multi-line": + System.out.println("\tToggle multi-line input mode."); + 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 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/base/src/bjc/dicelang/cli/DiceLangPragma.java b/base/src/bjc/dicelang/cli/DiceLangPragma.java new file mode 100644 index 0000000..9bbdf49 --- /dev/null +++ b/base/src/bjc/dicelang/cli/DiceLangPragma.java @@ -0,0 +1,36 @@ +package bjc.dicelang.cli; + +import bjc.dicelang.DiceLangEngine; + +/** + * Represents a pragma for the command interface. + * + * @author EVE + * + */ +public interface DiceLangPragma { + /** + * Execute the pragma. + * + * @param lne + * The command line the pragma came from. + * @param eng + * The engine we are attached to. + * @return Whether or not the pragma succeeded. + */ + public boolean execute(String lne, DiceLangEngine eng); + + /** + * Get a description on how to use this pragma + * + * @return The description on how to use the pragma + */ + public String getDescription(); + + /** + * Get a brief idea on what this pragma does + * + * @return A brief description of what this pragma does. + */ + public String getBrief(); +} diff --git a/base/src/bjc/dicelang/eval/DiceEvaluatorResult.java b/base/src/bjc/dicelang/eval/DiceEvaluatorResult.java index 8e50333..02d01ae 100644 --- a/base/src/bjc/dicelang/eval/DiceEvaluatorResult.java +++ b/base/src/bjc/dicelang/eval/DiceEvaluatorResult.java @@ -25,7 +25,7 @@ public class DiceEvaluatorResult extends EvaluatorResult { public DiceEvaluatorResult(DieList list) { this(new ListDiceExpression(list)); } - + public boolean isList() { return diceVal.isList(); } diff --git a/base/src/bjc/dicelang/eval/Evaluator.java b/base/src/bjc/dicelang/eval/Evaluator.java index 4cc2a1e..4603e22 100644 --- a/base/src/bjc/dicelang/eval/Evaluator.java +++ b/base/src/bjc/dicelang/eval/Evaluator.java @@ -6,11 +6,8 @@ import java.util.LinkedList; import java.util.function.Consumer; import bjc.dicelang.DiceLangEngine; -import bjc.dicelang.DiceToken; import bjc.dicelang.Errors; -import bjc.dicelang.FloatToken; import bjc.dicelang.Node; -import bjc.dicelang.Token; import bjc.dicelang.dice.CompoundDie; import bjc.dicelang.dice.Die; import bjc.dicelang.dice.MathDie; @@ -18,7 +15,9 @@ import bjc.dicelang.dice.ScalarDiceExpression; import bjc.dicelang.dice.ScalarDie; import bjc.dicelang.dice.SimpleDie; import bjc.dicelang.dice.SimpleDieList; - +import bjc.dicelang.tokens.DiceToken; +import bjc.dicelang.tokens.FloatToken; +import bjc.dicelang.tokens.Token; import bjc.utils.data.ITree; import bjc.utils.data.SingleIterator; import bjc.utils.data.TopDownTransformIterator; @@ -64,7 +63,7 @@ public class Evaluator { * Create a new evaluator. * * @param en - * The engine. + * The engine. */ public Evaluator(final DiceLangEngine en) { eng = en; @@ -74,7 +73,7 @@ public class Evaluator { * Evaluate a AST. * * @param comm - * The AST to evaluate. + * The AST to evaluate. * * @return The result of the tree. */ @@ -84,16 +83,18 @@ public class Evaluator { 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. + * 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()) { + while(itr.hasNext()) { itr.next(); } }; /* The result. */ - final ITree res = comm.topDownTransform(this::pickEvaluationType, node -> this.evaluateNode(node, ctx)); + final ITree res = comm.topDownTransform(this::pickEvaluationType, + node -> this.evaluateNode(node, ctx)); return res.getHead().resultVal; } @@ -117,9 +118,9 @@ public class Evaluator { /* Pick the way to evaluate a node. */ private TopDownTransformResult pickEvaluationType(final Node nd) { - switch (nd.type) { + switch(nd.type) { case UNARYOP: - switch (nd.operatorType) { + switch(nd.operatorType) { case COERCE: /* Coerce does special things to the tree. */ return TopDownTransformResult.RTRANSFORM; @@ -134,7 +135,7 @@ public class Evaluator { /* Evaluate a node. */ private ITree evaluateNode(final ITree ast, final Context ctx) { - switch (ast.getHead().type) { + switch(ast.getHead().type) { case UNARYOP: return evaluateUnaryOp(ast, ctx); case BINOP: @@ -154,23 +155,23 @@ public class Evaluator { /* Evaluate a unary operator. */ private ITree evaluateUnaryOp(final ITree ast, final Context ctx) { /* Unary operators only take one operand. */ - if (ast.getChildrenCount() != 1) { + if(ast.getChildrenCount() != 1) { Errors.inst.printError(EK_EVAL_UNUNARY, Integer.toString(ast.getChildrenCount())); return new Tree<>(Node.FAIL(ast)); } - switch (ast.getHead().operatorType) { + 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. + * 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). + * Coerce also needs to be able to coerce things to dice and + * ratios (whenever they get added). */ case COERCE: final ITree toCoerce = ast.getChild(0); @@ -180,16 +181,16 @@ public class Evaluator { /* The current type we are coercing to. */ CoerceSteps curLevel = CoerceSteps.INTEGER; - for (int i = 0; i < toCoerce.getChildrenCount(); i++) { + for(int i = 0; i < toCoerce.getChildrenCount(); i++) { final ITree child = toCoerce.getChild(i); ITree nChild = null; /* Tell our thunk we processed a node. */ - if (ctx.isDebug) { + if(ctx.isDebug) { /* Evaluate each step of the child. */ final Iterator> nd = stepDebug(child); - for (; nd.hasNext(); nChild = nd.next()) { + for(; nd.hasNext(); nChild = nd.next()) { ctx.thunk.accept(new SingleIterator<>(child)); } } else { @@ -199,7 +200,7 @@ public class Evaluator { ctx.thunk.accept(new SingleIterator<>(nChild)); } - if (nChild == null) { + if(nChild == null) { Errors.inst.printError(EK_EVAL_INVNODE); return new Tree<>(Node.FAIL(ast)); } @@ -208,21 +209,23 @@ public class Evaluator { final EvaluatorResult res = childNode.resultVal; /* Move up to coercing to a float. */ - if (res.type == FLOAT) { + if(res.type == FLOAT) { curLevel = CoerceSteps.DOUBLE; } children.add(nChild); } - for (final ITree child : children) { + for(final ITree child : children) { final Node nd = child.getHead(); final EvaluatorResult res = nd.resultVal; - switch (res.type) { + switch(res.type) { case INT: - /* Coerce ints to doubles if we need to. */ - if (curLevel == CoerceSteps.DOUBLE) { + /* + * Coerce ints to doubles if we need to. + */ + if(curLevel == CoerceSteps.DOUBLE) { nd.resultVal = new FloatEvaluatorResult((double) res.intVal); } default: @@ -237,7 +240,7 @@ public class Evaluator { case DICESCALAR: final EvaluatorResult opr = ast.getChild(0).getHead().resultVal; - if (opr.type != INT) { + if(opr.type != INT) { Errors.inst.printError(EK_EVAL_INVDCREATE, opr.type.toString()); } @@ -246,7 +249,7 @@ public class Evaluator { case DICEFUDGE: final EvaluatorResult oprn = ast.getChild(0).getHead().resultVal; - if (oprn.type != INT) { + if(oprn.type != INT) { Errors.inst.printError(EK_EVAL_INVDCREATE, oprn.type.toString()); } @@ -263,8 +266,9 @@ public class Evaluator { 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()); + if(ast.getChildrenCount() != 2) { + Errors.inst.printError(EK_EVAL_INVBIN, Integer.toString(ast.getChildrenCount()), + ast.toString()); return new Tree<>(Node.FAIL(ast)); } @@ -275,7 +279,7 @@ public class Evaluator { final EvaluatorResult leftRes = left.getHead().resultVal; final EvaluatorResult rightRes = right.getHead().resultVal; - switch (binOp) { + switch(binOp) { case ADD: case SUBTRACT: case MULTIPLY: @@ -298,16 +302,16 @@ public class Evaluator { /* Evaluate a binary operator on strings. */ private static ITree evaluateStringBinary(final Token.Type op, final EvaluatorResult left, final EvaluatorResult right, final Context ctx) { - if (left.type != STRING) { + if(left.type != STRING) { Errors.inst.printError(EK_EVAL_INVSTRING, left.type.toString()); return new Tree<>(Node.FAIL(left)); } final String strang = ((StringEvaluatorResult) left).stringVal; - switch (op) { + switch(op) { case STRCAT: - if (right.type != STRING) { + if(right.type != STRING) { Errors.inst.printError(EK_EVAL_UNSTRING, right.type.toString()); return new Tree<>(Node.FAIL(right)); } @@ -317,7 +321,7 @@ public class Evaluator { return new Tree<>(new Node(Node.Type.RESULT, cres)); case STRREP: - if (right.type != INT) { + if(right.type != INT) { Errors.inst.printError(EK_EVAL_INVSTRING, right.type.toString()); return new Tree<>(Node.FAIL(right)); } @@ -325,7 +329,7 @@ public class Evaluator { String res = strang; final long count = right.intVal; - for (long i = 1; i < count; i++) { + for(long i = 1; i < count; i++) { res += strang; } @@ -341,7 +345,7 @@ public class Evaluator { final EvaluatorResult right, final Context ctx) { EvaluatorResult res = null; - switch (op) { + switch(op) { /* * @TODO 10/09/17 Ben Culkin :DiceSimplify * @@ -350,27 +354,27 @@ public class Evaluator { * ADDENDA: Replace the .diceVal.isList() with .isList() */ case DICEGROUP: - if (left.type == DICE && !((DiceEvaluatorResult) left).diceVal.isList()) { + if(left.type == DICE && !((DiceEvaluatorResult) left).diceVal.isList()) { Die lhs = ((ScalarDiceExpression) ((DiceEvaluatorResult) left).diceVal).scalar; - if (right.type == DICE && !((DiceEvaluatorResult) right).diceVal.isList()) { + if(right.type == DICE && !((DiceEvaluatorResult) right).diceVal.isList()) { Die rhs = ((ScalarDiceExpression) ((DiceEvaluatorResult) right).diceVal).scalar; Die simple = new SimpleDie(lhs, rhs); res = new DiceEvaluatorResult(simple); - } else if (right.type == INT) { + } else if(right.type == INT) { res = new DiceEvaluatorResult(new SimpleDie(lhs, right.intVal)); } else { Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); return new Tree<>(Node.FAIL(right)); } - } else if (left.type == INT) { - if (right.type == DICE && !((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(left.type == INT) { + if(right.type == DICE && !((DiceEvaluatorResult) right).diceVal.isList()) { Die rhs = ((ScalarDiceExpression) ((DiceEvaluatorResult) right).diceVal).scalar; res = new DiceEvaluatorResult(new SimpleDie(left.intVal, rhs)); - } else if (right.type == INT) { + } else if(right.type == INT) { res = new DiceEvaluatorResult(new SimpleDie(left.intVal, right.intVal)); } else { Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); @@ -382,10 +386,10 @@ public class Evaluator { } case DICECONCAT: - if (left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) { + if(left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString()); return new Tree<>(Node.FAIL(left)); - } else if (right.type != DICE || ((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(right.type != DICE || ((DiceEvaluatorResult) right).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString()); return new Tree<>(Node.FAIL(right)); } else { @@ -398,10 +402,10 @@ public class Evaluator { break; case DICELIST: - if (left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) { + if(left.type != DICE || ((DiceEvaluatorResult) left).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, left.type.toString()); return new Tree<>(Node.FAIL(left)); - } else if (right.type != DICE || ((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(right.type != DICE || ((DiceEvaluatorResult) right).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, right.type.toString()); return new Tree<>(Node.FAIL(right)); } else { @@ -424,42 +428,42 @@ public class Evaluator { /* Evaluate a binary math operator. */ private static ITree evaluateMathBinary(final Token.Type op, final EvaluatorResult left, final EvaluatorResult right, final Context ctx) { - if (left.type == STRING || right.type == STRING) { + if(left.type == STRING || right.type == STRING) { Errors.inst.printError(EK_EVAL_STRINGMATH); return new Tree<>(Node.FAIL()); - } else if (left.type == FAILURE || right.type == FAILURE) { + } else if(left.type == FAILURE || right.type == FAILURE) { return new Tree<>(Node.FAIL()); - } else if (left.type == INT && right.type != INT) { + } else if(left.type == INT && right.type != INT) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(right)); - } else if (left.type == FLOAT && right.type != FLOAT) { + } else if(left.type == FLOAT && right.type != FLOAT) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(right)); - } else if (left.type == DICE && right.type != DICE) { + } else if(left.type == DICE && right.type != DICE) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(right)); - } else if (right.type == INT && left.type != INT) { + } else if(right.type == INT && left.type != INT) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(left)); - } else if (right.type == FLOAT && left.type != FLOAT) { + } else if(right.type == FLOAT && left.type != FLOAT) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(left)); - } else if (right.type == DICE && left.type != DICE) { + } else if(right.type == DICE && left.type != DICE) { Errors.inst.printError(EK_EVAL_MISMATH); return new Tree<>(Node.FAIL(left)); } EvaluatorResult res = null; - switch (op) { + switch(op) { case ADD: - if (left.type == INT) { + if(left.type == INT) { res = new EvaluatorResult(INT, left.intVal + right.intVal); - } else if (left.type == DICE) { - if (((DiceEvaluatorResult) left).diceVal.isList()) { + } else if(left.type == DICE) { + if(((DiceEvaluatorResult) left).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, left.toString()); return new Tree<>(Node.FAIL(left)); - } else if (((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(((DiceEvaluatorResult) right).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, right.toString()); return new Tree<>(Node.FAIL(right)); } @@ -469,20 +473,20 @@ public class Evaluator { res = new DiceEvaluatorResult(new MathDie(MathDie.MathOp.ADD, lhs, rhs)); } else { - res = new FloatEvaluatorResult( - ((FloatEvaluatorResult) left).floatVal + ((FloatEvaluatorResult) right).floatVal); + res = new FloatEvaluatorResult(((FloatEvaluatorResult) left).floatVal + + ((FloatEvaluatorResult) right).floatVal); } break; case SUBTRACT: - if (left.type == INT) { + if(left.type == INT) { res = new EvaluatorResult(INT, left.intVal - right.intVal); - } else if (left.type == DICE) { - if (((DiceEvaluatorResult) left).diceVal.isList()) { + } else if(left.type == DICE) { + if(((DiceEvaluatorResult) left).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, left.toString()); return new Tree<>(Node.FAIL(left)); - } else if (((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(((DiceEvaluatorResult) right).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, right.toString()); return new Tree<>(Node.FAIL(right)); } @@ -492,20 +496,20 @@ public class Evaluator { res = new DiceEvaluatorResult(new MathDie(MathDie.MathOp.SUBTRACT, lhs, rhs)); } else { - res = new FloatEvaluatorResult( - ((FloatEvaluatorResult) left).floatVal - ((FloatEvaluatorResult) right).floatVal); + res = new FloatEvaluatorResult(((FloatEvaluatorResult) left).floatVal + - ((FloatEvaluatorResult) right).floatVal); } break; case MULTIPLY: - if (left.type == INT) { + if(left.type == INT) { res = new EvaluatorResult(INT, left.intVal * right.intVal); - } else if (left.type == DICE) { - if (((DiceEvaluatorResult) left).diceVal.isList()) { + } else if(left.type == DICE) { + if(((DiceEvaluatorResult) left).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, left.toString()); return new Tree<>(Node.FAIL(left)); - } else if (((DiceEvaluatorResult) right).diceVal.isList()) { + } else if(((DiceEvaluatorResult) right).diceVal.isList()) { Errors.inst.printError(EK_EVAL_INVDICE, right.toString()); return new Tree<>(Node.FAIL(right)); } @@ -515,27 +519,27 @@ public class Evaluator { res = new DiceEvaluatorResult(new MathDie(MathDie.MathOp.MULTIPLY, lhs, rhs)); } else { - res = new FloatEvaluatorResult( - ((FloatEvaluatorResult) left).floatVal * ((FloatEvaluatorResult) right).floatVal); + res = new FloatEvaluatorResult(((FloatEvaluatorResult) left).floatVal + * ((FloatEvaluatorResult) right).floatVal); } break; case DIVIDE: - if (left.type == INT) { - if (right.intVal == 0) { + if(left.type == INT) { + if(right.intVal == 0) { Errors.inst.printError(EK_EVAL_DIVZERO); res = new FailureEvaluatorResult(right); } else { res = new EvaluatorResult(FLOAT, left.intVal / right.intVal); } - } else if (left.type == FLOAT) { - if (((FloatEvaluatorResult) right).floatVal == 0) { + } else if(left.type == FLOAT) { + if(((FloatEvaluatorResult) right).floatVal == 0) { Errors.inst.printError(EK_EVAL_DIVZERO); res = new FailureEvaluatorResult(right); } else { - res = new FloatEvaluatorResult( - ((FloatEvaluatorResult) left).floatVal / ((FloatEvaluatorResult) right).floatVal); + res = new FloatEvaluatorResult(((FloatEvaluatorResult) left).floatVal + / ((FloatEvaluatorResult) right).floatVal); } } else { Errors.inst.printError(EK_EVAL_DIVDICE); @@ -545,20 +549,20 @@ public class Evaluator { break; case IDIVIDE: - if (left.type == INT) { - if (right.intVal == 0) { + if(left.type == INT) { + if(right.intVal == 0) { Errors.inst.printError(EK_EVAL_DIVZERO); res = new FailureEvaluatorResult(right); } else { res = new EvaluatorResult(INT, (int) (left.intVal / right.intVal)); } - } else if (left.type == FLOAT) { - if (((FloatEvaluatorResult) right).floatVal == 0) { + } else if(left.type == FLOAT) { + if(((FloatEvaluatorResult) right).floatVal == 0) { Errors.inst.printError(EK_EVAL_DIVZERO); res = new FailureEvaluatorResult(right); } else { - res = new EvaluatorResult(INT, - (int) (((FloatEvaluatorResult) left).floatVal / ((FloatEvaluatorResult) right).floatVal)); + res = new EvaluatorResult(INT, (int) (((FloatEvaluatorResult) left).floatVal + / ((FloatEvaluatorResult) right).floatVal)); } } else { Errors.inst.printError(EK_EVAL_DIVDICE); @@ -579,7 +583,7 @@ public class Evaluator { private ITree evaluateTokenRef(final Token tk, final Context ctx) { EvaluatorResult res = null; - switch (tk.type) { + switch(tk.type) { case INT_LIT: res = new EvaluatorResult(INT, tk.intValue); break; diff --git a/base/src/bjc/dicelang/eval/EvaluatorResult.java b/base/src/bjc/dicelang/eval/EvaluatorResult.java index 3ac0202..1a783ad 100644 --- a/base/src/bjc/dicelang/eval/EvaluatorResult.java +++ b/base/src/bjc/dicelang/eval/EvaluatorResult.java @@ -57,7 +57,7 @@ public class EvaluatorResult { * Create a new result. * * @param typ - * The type of the result. + * The type of the result. */ protected EvaluatorResult(final EvaluatorResult.Type typ) { type = typ; diff --git a/base/src/bjc/dicelang/eval/FailureEvaluatorResult.java b/base/src/bjc/dicelang/eval/FailureEvaluatorResult.java index 3b641db..d3b2cbe 100644 --- a/base/src/bjc/dicelang/eval/FailureEvaluatorResult.java +++ b/base/src/bjc/dicelang/eval/FailureEvaluatorResult.java @@ -9,14 +9,14 @@ public class FailureEvaluatorResult extends EvaluatorResult { * Original node data */ public ITree origVal; - + public FailureEvaluatorResult() { super(Type.FAILURE); } - + public FailureEvaluatorResult(final ITree orig) { super(Type.FAILURE); - + origVal = orig; } @@ -38,18 +38,13 @@ public class FailureEvaluatorResult extends EvaluatorResult { @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; + if(this == obj) return true; + if(obj == null) return false; + if(getClass() != obj.getClass()) return false; FailureEvaluatorResult other = (FailureEvaluatorResult) obj; - if (origVal == null) { - if (other.origVal != null) - return false; - } else if (!origVal.equals(other.origVal)) - return false; + if(origVal == null) { + if(other.origVal != null) return false; + } else if(!origVal.equals(other.origVal)) return false; return true; } } diff --git a/base/src/bjc/dicelang/eval/FloatEvaluatorResult.java b/base/src/bjc/dicelang/eval/FloatEvaluatorResult.java index 7fbbcdc..22f89f0 100644 --- a/base/src/bjc/dicelang/eval/FloatEvaluatorResult.java +++ b/base/src/bjc/dicelang/eval/FloatEvaluatorResult.java @@ -5,13 +5,13 @@ public class FloatEvaluatorResult extends EvaluatorResult { * The float value of the result. */ public double floatVal; - + public FloatEvaluatorResult(double val) { super(Type.FLOAT); - + floatVal = val; } - + @Override public String toString() { return super.toString() + "(" + floatVal + ")"; @@ -29,15 +29,11 @@ public class FloatEvaluatorResult extends EvaluatorResult { @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; + if(this == obj) return true; + if(obj == null) return false; + if(getClass() != obj.getClass()) return false; FloatEvaluatorResult other = (FloatEvaluatorResult) obj; - if (Double.doubleToLongBits(floatVal) != Double.doubleToLongBits(other.floatVal)) - return false; + if(Double.doubleToLongBits(floatVal) != Double.doubleToLongBits(other.floatVal)) return false; return true; } } diff --git a/base/src/bjc/dicelang/eval/StringEvaluatorResult.java b/base/src/bjc/dicelang/eval/StringEvaluatorResult.java index 870fd01..251b318 100644 --- a/base/src/bjc/dicelang/eval/StringEvaluatorResult.java +++ b/base/src/bjc/dicelang/eval/StringEvaluatorResult.java @@ -8,10 +8,10 @@ public class StringEvaluatorResult extends EvaluatorResult { public StringEvaluatorResult(String strang) { super(Type.STRING); - + stringVal = strang; } - + @Override public String toString() { return super.toString() + "(" + stringVal + ")"; @@ -27,18 +27,13 @@ public class StringEvaluatorResult extends EvaluatorResult { @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; + if(this == obj) return true; + if(obj == null) return false; + if(getClass() != obj.getClass()) return false; StringEvaluatorResult other = (StringEvaluatorResult) obj; - if (stringVal == null) { - if (other.stringVal != null) - return false; - } else if (!stringVal.equals(other.stringVal)) - return false; + if(stringVal == null) { + if(other.stringVal != null) return false; + } else if(!stringVal.equals(other.stringVal)) return false; return true; } } diff --git a/base/src/bjc/dicelang/expr/ExprREPL.java b/base/src/bjc/dicelang/expr/ExprREPL.java index 49b9575..d763d67 100644 --- a/base/src/bjc/dicelang/expr/ExprREPL.java +++ b/base/src/bjc/dicelang/expr/ExprREPL.java @@ -17,7 +17,7 @@ public class ExprREPL { * Main method. * * @param args - * Unused CLI args. + * Unused CLI args. */ public static void main(final String[] args) { /* Create our objects. */ @@ -32,7 +32,7 @@ public class ExprREPL { String ln = scan.nextLine().trim(); /* Enter REPL loop. */ - while (!ln.equals("")) { + while(!ln.equals("")) { /* Print raw command. */ System.out.println("Raw command: " + ln); System.out.println(); @@ -40,13 +40,13 @@ public class ExprREPL { /* Lex command to infix tokens. */ final Token[] infixTokens = lex.lexString(ln, toks); System.out.println("Lexed tokens: "); - for (final Token tok : infixTokens) { + for(final Token tok : infixTokens) { System.out.println("\t" + tok); } /* Print out infix expression. */ System.out.print("Lexed expression: "); - for (final Token tok : infixTokens) { + for(final Token tok : infixTokens) { System.out.print(tok.toExpr() + " "); } @@ -57,13 +57,13 @@ public class ExprREPL { /* Shunt infix tokens to postfix tokens. */ final IList postfixTokens = Shunter.shuntTokens(infixTokens); System.out.println("Lexed tokens: "); - for (final Token tok : postfixTokens) { + for(final Token tok : postfixTokens) { System.out.println("\t" + tok); } /* Print out postfix tokens. */ System.out.print("Shunted expression: "); - for (final Token tok : postfixTokens) { + for(final Token tok : postfixTokens) { System.out.print(tok.toExpr() + " "); } @@ -71,10 +71,15 @@ public class ExprREPL { System.out.println(); System.out.println(); - /* Construct a tree from the list of postfixed tokens. */ - final ITree ast = TreeConstructor.constructTree(postfixTokens, tok -> tok.typ.isOperator); + /* + * Construct a tree from the list of postfixed tokens. + */ + final ITree ast = TreeConstructor.constructTree(postfixTokens, + tok -> tok.typ.isOperator); - /* Print the tree, then the canonical expression for it. */ + /* + * Print the tree, then the canonical expression for it. + */ System.out.println("Parsed tree"); System.out.println(ast.toString()); System.out.println("\nCanonical expr: " + Parser.toCanonicalExpr(ast)); diff --git a/base/src/bjc/dicelang/expr/Ezpr.java b/base/src/bjc/dicelang/expr/Ezpr.java index 4919c81..2a54b6e 100644 --- a/base/src/bjc/dicelang/expr/Ezpr.java +++ b/base/src/bjc/dicelang/expr/Ezpr.java @@ -42,7 +42,7 @@ public class Ezpr { @Override public String toString() { - if (typ == TOKEN) { + if(typ == TOKEN) { return tok.toString(); } return ezp.toString(); @@ -65,26 +65,28 @@ public class Ezpr { HashMultiset newPositive = HashMultiset.create(); HashMultiset newNegative = HashMultiset.create(); - for (EzprNode nd : positive) { + for(EzprNode nd : positive) { /* Flatten enclosed ezprs of the same type. */ - if (nd.typ == EZPR && (nd.ezp.typ == typ)) { + 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) { + if(typ == SUM) { + /* + * Add sum parts to corresponding bags. + */ + for(EzprNode knd : kid.positive) { newPositive.add(knd); } - for (EzprNode knd : kid.negative) { + for(EzprNode knd : kid.negative) { newNegative.add(knd); } } else { /* @TODO ensure that this is correct. */ - for (EzprNode knd : kid.positive) { + for(EzprNode knd : kid.positive) { newPositive.add(knd); } - for (EzprNode knd : kid.negative) { + for(EzprNode knd : kid.negative) { newNegative.add(knd); } } @@ -93,25 +95,25 @@ public class Ezpr { } } - for (EzprNode nd : negative) { + for(EzprNode nd : negative) { /* Flatten enclosed ezprs of the same type. */ - if (nd.typ == EZPR && (nd.ezp.typ == typ)) { + 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) { + if(typ == SUM) { + for(EzprNode knd : kid.positive) { newNegative.add(knd); } - for (EzprNode knd : kid.negative) { + for(EzprNode knd : kid.negative) { newPositive.add(knd); } } else { - for (EzprNode knd : kid.positive) { + for(EzprNode knd : kid.positive) { newNegative.add(knd); } - for (EzprNode knd : kid.negative) { + for(EzprNode knd : kid.negative) { newPositive.add(knd); } } @@ -128,13 +130,13 @@ public class Ezpr { StringBuilder sb = new StringBuilder(typ.toString()); sb.append(" [ "); - for (EzprNode nd : positive) { + for(EzprNode nd : positive) { sb.append(nd.toString()); sb.append(" "); } sb.append("# "); - for (EzprNode nd : negative) { + for(EzprNode nd : negative) { sb.append(nd.toString()); sb.append(" "); } diff --git a/base/src/bjc/dicelang/expr/Lexer.java b/base/src/bjc/dicelang/expr/Lexer.java index c7dd92f..c43050b 100644 --- a/base/src/bjc/dicelang/expr/Lexer.java +++ b/base/src/bjc/dicelang/expr/Lexer.java @@ -34,10 +34,10 @@ public class Lexer { * Convert a string from a input command to a series of infix tokens. * * @param inp - * The input command. + * The input command. * * @param tks - * The token state. + * The token state. * * @return A series of infix tokens representing the command. */ @@ -48,7 +48,7 @@ public class Lexer { final List tokens = new LinkedList<>(); /* Process each token. */ - for (final String spacedToken : spacedTokens) { + for(final String spacedToken : spacedTokens) { /* Split on operators. */ final IList splitTokens = split.split(spacedToken); diff --git a/base/src/bjc/dicelang/expr/Parser.java b/base/src/bjc/dicelang/expr/Parser.java index 1156334..020467a 100644 --- a/base/src/bjc/dicelang/expr/Parser.java +++ b/base/src/bjc/dicelang/expr/Parser.java @@ -9,13 +9,13 @@ import bjc.utils.data.ITree; */ public class Parser { /* - * Convert an expression to one that uses the smallest necessary amount of - * parens. + * Convert an expression to one that uses the smallest necessary amount + * of parens. */ public static String toCanonicalExpr(final ITree ast) { final Token data = ast.getHead(); - if (ast.getChildrenCount() == 0) { + if(ast.getChildrenCount() == 0) { /* Handle leaf nodes. */ return data.toExpr(); } @@ -29,21 +29,21 @@ public class Parser { String rightExpr = toCanonicalExpr(right); /* Add parens if the left was higher priority. */ - if (left.getChildrenCount() == 0) { + if(left.getChildrenCount() == 0) { int leftPriority = left.getHead().typ.operatorPriority; int dataPriority = data.typ.operatorPriority; - if (leftPriority >= dataPriority) { + if(leftPriority >= dataPriority) { leftExpr = String.format("(%s)", leftExpr); } } /* Add parens if the right was higher priority. */ - if (right.getChildrenCount() == 0) { + if(right.getChildrenCount() == 0) { int rightPriority = right.getHead().typ.operatorPriority; int dataPriority = data.typ.operatorPriority; - if (rightPriority >= dataPriority) { + if(rightPriority >= dataPriority) { rightExpr = String.format("(%s)", rightExpr); } } diff --git a/base/src/bjc/dicelang/expr/Shunter.java b/base/src/bjc/dicelang/expr/Shunter.java index 53c2298..3d2a523 100644 --- a/base/src/bjc/dicelang/expr/Shunter.java +++ b/base/src/bjc/dicelang/expr/Shunter.java @@ -16,7 +16,7 @@ public class Shunter { * Convert a infix series of tokens to a postfix series of tokens. * * @param infixTokens - * The tokens in infix order. + * The tokens in infix order. * * @return The tokens in postfix order. */ @@ -28,20 +28,22 @@ public class Shunter { final Deque opStack = new LinkedList<>(); /* Shunt each token. */ - for (final Token tok : infixTokens) { + for(final Token tok : infixTokens) { /* Handle operators. */ - if (tok.typ.isOperator) { + if(tok.typ.isOperator) { Token curOp = opStack.peek(); /* - * Check if an operator is higher priority, respecting their left associativity. + * Check if an operator is higher priority, + * respecting their left associativity. * - * @NOTE Should this be factored out into a method? + * @NOTE Should this be factored out into a + * method? */ int leftPriority = tok.typ.operatorPriority; int rightPriority; - if (curOp == null) { + if(curOp == null) { rightPriority = 0; } else { rightPriority = curOp.typ.operatorPriority; @@ -50,14 +52,15 @@ public class Shunter { boolean isHigherPrec = leftPriority >= rightPriority; /* - * Pop all operators that are lower precedence than us. + * Pop all operators that are lower precedence + * than us. */ - while (!opStack.isEmpty() && isHigherPrec) { + while(!opStack.isEmpty() && isHigherPrec) { postfixTokens.add(opStack.pop()); curOp = opStack.peek(); leftPriority = tok.typ.operatorPriority; - if (curOp == null) { + if(curOp == null) { rightPriority = 0; } else { rightPriority = curOp.typ.operatorPriority; @@ -67,21 +70,22 @@ public class Shunter { } opStack.push(tok); - } else if (tok.typ == TokenType.OPAREN) { + } else if(tok.typ == TokenType.OPAREN) { opStack.push(tok); - } else if (tok.typ == TokenType.CPAREN) { + } else if(tok.typ == TokenType.CPAREN) { Token curOp = opStack.peek(); /* - * Pop things until we find the matching parenthesis. + * Pop things until we find the matching + * parenthesis. */ - while (curOp.typ != TokenType.OPAREN) { + while(curOp.typ != TokenType.OPAREN) { final Token tk = opStack.pop(); postfixTokens.add(tk); curOp = opStack.peek(); } - if (!opStack.isEmpty()) { + if(!opStack.isEmpty()) { opStack.pop(); } } else { @@ -92,7 +96,7 @@ public class Shunter { /* * Flush remaining operators. */ - while (!opStack.isEmpty()) { + while(!opStack.isEmpty()) { postfixTokens.add(opStack.pop()); } diff --git a/base/src/bjc/dicelang/expr/Token.java b/base/src/bjc/dicelang/expr/Token.java index 750362d..f083577 100644 --- a/base/src/bjc/dicelang/expr/Token.java +++ b/base/src/bjc/dicelang/expr/Token.java @@ -33,13 +33,13 @@ public class Token { * Create a new token. * * @param type - * The type of this token. + * The type of this token. * * @param raw - * The string this token came from. + * The string this token came from. * * @param toks - * The state for this token + * The state for this token */ public Token(final TokenType type, final String raw, final Tokens toks) { this.typ = type; @@ -53,7 +53,7 @@ public class Token { String typeStr = typ.toString(); typeStr = String.format("%s (%s)", typeStr, typ.name()); - if (typ == TokenType.VREF) { + if(typ == TokenType.VREF) { typeStr += " (ind. " + intValue; typeStr += ", sym. \"" + tks.symbolTable.get(intValue) + "\")"; } @@ -67,7 +67,7 @@ public class Token { * @return The string representation of it. */ public String toExpr() { - switch (typ) { + switch(typ) { case ADD: return "+"; case SUBTRACT: diff --git a/base/src/bjc/dicelang/expr/TokenType.java b/base/src/bjc/dicelang/expr/TokenType.java index 71dd597..93de6d9 100644 --- a/base/src/bjc/dicelang/expr/TokenType.java +++ b/base/src/bjc/dicelang/expr/TokenType.java @@ -10,8 +10,8 @@ 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. + * numbered because this was an assignment for PoPL and that was what + * Dr. Naz wanted. */ /** Represents + */ diff --git a/base/src/bjc/dicelang/expr/Tokens.java b/base/src/bjc/dicelang/expr/Tokens.java index 687a414..c307391 100644 --- a/base/src/bjc/dicelang/expr/Tokens.java +++ b/base/src/bjc/dicelang/expr/Tokens.java @@ -58,14 +58,14 @@ public class Tokens { * Convert the string representation of a token into a token. * * @param tok - * The string representation of the token. + * The string representation of the token. * @param raw - * The original string the token came from. + * 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)) { + if(litTokens.containsKey(tok)) { /* Return matching literal token. */ return new Token(litTokens.get(tok), raw, this); } @@ -78,7 +78,7 @@ public class Tokens { private Token parseVRef(final String tok, final String raw) { final Token tk = new Token(TokenType.VREF, raw, this); - if (revSymTab.containsKey(tok)) { + if(revSymTab.containsKey(tok)) { /* Reuse the entry if it exists. */ tk.intValue = revSymTab.get(tok); } else { diff --git a/base/src/bjc/dicelang/tokens/DiceToken.java b/base/src/bjc/dicelang/tokens/DiceToken.java new file mode 100644 index 0000000..4bf2068 --- /dev/null +++ b/base/src/bjc/dicelang/tokens/DiceToken.java @@ -0,0 +1,38 @@ +package bjc.dicelang.tokens; + +import bjc.dicelang.dice.DiceExpression; + +public class DiceToken extends Token { + public DiceExpression diceValue; + + public DiceToken(DiceExpression val) { + super(Type.DICE_LIT); + + diceValue = val; + } + + @Override + public String toString() { + return super.toString() + "(" + diceValue + ")"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((diceValue == null) ? 0 : diceValue.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) return true; + if(!super.equals(obj)) return false; + if(getClass() != obj.getClass()) return false; + DiceToken other = (DiceToken) obj; + if(diceValue == null) { + if(other.diceValue != null) return false; + } else if(!diceValue.equals(other.diceValue)) return false; + return true; + } +} diff --git a/base/src/bjc/dicelang/tokens/FloatToken.java b/base/src/bjc/dicelang/tokens/FloatToken.java new file mode 100644 index 0000000..f56bef7 --- /dev/null +++ b/base/src/bjc/dicelang/tokens/FloatToken.java @@ -0,0 +1,36 @@ +package bjc.dicelang.tokens; + +public class FloatToken extends Token { + public double floatValue; + + public FloatToken(double val) { + super(Type.FLOAT_LIT); + + floatValue = val; + } + + @Override + public String toString() { + return super.toString() + "(" + floatValue + ")"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(floatValue); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) return true; + if(!super.equals(obj)) return false; + if(getClass() != obj.getClass()) return false; + FloatToken other = (FloatToken) obj; + if(Double.doubleToLongBits(floatValue) != Double.doubleToLongBits(other.floatValue)) return false; + return true; + } +} diff --git a/base/src/bjc/dicelang/tokens/IntToken.java b/base/src/bjc/dicelang/tokens/IntToken.java new file mode 100644 index 0000000..5ff4b7c --- /dev/null +++ b/base/src/bjc/dicelang/tokens/IntToken.java @@ -0,0 +1,26 @@ +package bjc.dicelang.tokens; + +/** + * Represents an integer literal. + * + * @author EVE + * + */ +public class IntToken extends Token { + /** + * The literal value. + */ + public final long value; + + /** + * Create a new integer literal. + * + * @param val + * The integer to use. + */ + public IntToken(long val) { + super(Type.INT_LIT); + + value = val; + } +} diff --git a/base/src/bjc/dicelang/tokens/Token.java b/base/src/bjc/dicelang/tokens/Token.java new file mode 100644 index 0000000..1a11ccd --- /dev/null +++ b/base/src/bjc/dicelang/tokens/Token.java @@ -0,0 +1,168 @@ +package bjc.dicelang.tokens; + +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. + */ + /* + * Math tokens. + */ + ADD, SUBTRACT, MULTIPLY, DIVIDE, IDIVIDE, + + /* + * Literal tokens. + */ + INT_LIT, FLOAT_LIT, STRING_LIT, VREF, DICE_LIT, + + /* + * Dice operators. + */ + DICESCALAR, DICEFUDGE, DICEGROUP, DICECONCAT, DICELIST, + + /* + * Expression operators. + */ + LET, BIND, COERCE, + + /* + * String operators. + */ + STRCAT, STRREP, + + /* + * Grouping operators. + */ + 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 + * + * - TOKGROUP (the tokens in the group) + * + * - TAG* (the tagged construct) + * + */ + public IList 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 IList 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 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/base/src/bjc/dicelang/util/ResourceLoader.java b/base/src/bjc/dicelang/util/ResourceLoader.java index 085081f..6777443 100644 --- a/base/src/bjc/dicelang/util/ResourceLoader.java +++ b/base/src/bjc/dicelang/util/ResourceLoader.java @@ -22,9 +22,10 @@ public class ResourceLoader { * Loads a .help file from the data/help directory. * * @param name - * The name of the help file to load. + * The name of the help file to load. * - * @return The contents of the help file, or null if it could not be opened. + * @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"); @@ -33,7 +34,7 @@ public class ResourceLoader { Path pth = Paths.get(fle.toURI()); return Files.lines(pth).toArray(sze -> new String[sze]); - } catch (IOException | URISyntaxException ioex) { + } catch(IOException | URISyntaxException ioex) { Errors.inst.printError(EK_MISC_IOEX, fle.toString()); } -- cgit v1.2.3