summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/examples
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-10-27 21:56:18 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-10-27 22:12:47 -0400
commite7413128ff4e376997de6e94e4bea5eca14811ef (patch)
tree0749e270fdb754d04dc223abd95d47436508047f /dice-lang/src/bjc/dicelang/examples
parente13a6981bd278c2cfc3b5ecb2517367b117f7a52 (diff)
Moved examples
Diffstat (limited to 'dice-lang/src/bjc/dicelang/examples')
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceASTLanguageTest.java261
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceASTPragma.java22
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceExpressionParserTest.java59
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceExpressionPreparer.java93
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceLanguageState.java37
-rw-r--r--dice-lang/src/bjc/dicelang/examples/DiceLanguageTest.java96
6 files changed, 568 insertions, 0 deletions
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceASTLanguageTest.java b/dice-lang/src/bjc/dicelang/examples/DiceASTLanguageTest.java
new file mode 100644
index 0000000..fa92fd2
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceASTLanguageTest.java
@@ -0,0 +1,261 @@
+package bjc.dicelang.examples;
+
+import java.util.InputMismatchException;
+import java.util.Scanner;
+
+import bjc.utils.data.ITree;
+import bjc.utils.funcdata.FunctionalMap;
+import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.funcdata.IList;
+import bjc.utils.funcdata.IMap;
+
+import bjc.dicelang.ast.DiceASTEvaluator;
+import bjc.dicelang.ast.DiceASTInliner;
+import bjc.dicelang.ast.DiceASTOptimizer;
+import bjc.dicelang.ast.DiceASTParser;
+import bjc.dicelang.ast.DiceASTReferenceSanitizer;
+import bjc.dicelang.ast.IResult;
+import bjc.dicelang.ast.nodes.IDiceASTNode;
+import bjc.dicelang.ast.optimization.ConstantCollapser;
+import bjc.dicelang.ast.optimization.OperationCondenser;
+
+/**
+ * Test interface for AST-based dice language
+ *
+ * @author ben
+ *
+ */
+public class DiceASTLanguageTest {
+ private static IMap<String, DiceASTPragma> actions;
+
+ private static DiceASTOptimizer optimizer;
+
+ // Set up things that need to be configured
+ static {
+ actions = new FunctionalMap<>();
+
+ // Inline all the variables in a given expression
+ actions.put("inline", DiceASTLanguageTest::handleInlineAction);
+
+ // Print out the enviroment
+ actions.put("env", (tokenizer, enviroment) -> {
+ enviroment.forEach((varName, varValue) -> {
+ System.out.println(varName + " is bound to " + varValue);
+ });
+ });
+
+ // Create and configure the optimizer
+ optimizer = new DiceASTOptimizer();
+
+ optimizer.addPass(new ConstantCollapser());
+ }
+
+ // Read in a command
+ private static String getNextCommand(Scanner inputSource,
+ int commandNumber) {
+ // Print a prompt using the current command number
+ System.out.print("\ndice-lang-" + commandNumber + "> ");
+
+ // Read in the next command
+ return inputSource.nextLine();
+ }
+
+ private static void handleInlineAction(
+ FunctionalStringTokenizer tokenizer,
+ IMap<String, ITree<IDiceASTNode>> enviroment) {
+ // Skip the pragma name
+ tokenizer.nextToken();
+
+ // Get the pragma arguments
+ IList<String> pragmaArgs = tokenizer.toList();
+
+ if (pragmaArgs.getSize() < 3) {
+ // Complain about pragma arguments not being valid
+ System.err.println(
+ "ERROR: Inline requires at least 3 parameters. They are:"
+ + "\n\t1. The name of the expression to inline."
+ + "\n\t2. The name of the variable to bind the result to."
+ + "\n\t3 and onwards. Names of variables to inline in the expression.");
+ } else {
+ // Get arguments
+ String inlineExpression = pragmaArgs.getByIndex(0);
+ String variableName = pragmaArgs.getByIndex(1);
+
+ // Grab the variables we want to inline
+ IList<String> inlinedVariables = pragmaArgs.tail().tail();
+
+ // Actually inline the variable
+ ITree<IDiceASTNode> inlinedExpression = DiceASTInliner
+ .selectiveInline(enviroment.get(inlineExpression),
+ enviroment, inlinedVariables);
+
+ // Stick the inlined variable into the enviroment
+ enviroment.put(variableName, inlinedExpression);
+ }
+ }
+
+ /**
+ * Main method of class
+ *
+ * @param args
+ * Unused CLI args
+ */
+ public static void main(String[] args) {
+ // Prepare the things we need for input
+ Scanner inputSource = new Scanner(System.in);
+ int commandNumber = 0;
+
+ // Grab the initial command
+ String currentLine = getNextCommand(inputSource, commandNumber);
+
+ // The enviroment for variables
+ IMap<String, ITree<IDiceASTNode>> enviroment = new FunctionalMap<>();
+
+ // Handle commands
+ while (!currentLine.equalsIgnoreCase("quit")) {
+ // Get the name of a possible action
+ String possibleActionName = currentLine.split(" ")[0];
+
+ // Check and see if we're executing an action
+ if (actions.containsKey(possibleActionName)) {
+ // Execute action
+ FunctionalStringTokenizer tokenizer = new FunctionalStringTokenizer(
+ currentLine);
+
+ // Execute the action
+ actions.get(possibleActionName).accept(tokenizer,
+ enviroment);
+
+ // Get the next command
+ currentLine = getNextCommand(inputSource, commandNumber);
+
+ continue;
+ }
+
+ // The AST we are going to build
+ ITree<IDiceASTNode> builtAST;
+
+ // Time command preparation
+ long time = System.nanoTime();
+
+ // Prepare the command
+ IList<String> preparedTokens = DiceExpressionPreparer
+ .prepareCommand(currentLine);
+
+ System.out.println("Command prepared in "
+ + (double) (System.nanoTime() - time) / 1000000000
+ + " s");
+
+ try {
+ // Time the AST creation
+ time = System.nanoTime();
+
+ // Create the AST
+ builtAST = DiceASTParser.createFromString(preparedTokens);
+
+ System.out
+ .println(
+ "Command parsed in "
+ + (double) (System.nanoTime()
+ - time) / 1000000000
+ + " s");
+ } catch (InputMismatchException | IllegalStateException
+ | UnsupportedOperationException ex) {
+ // Tell the user there was an error in parsing
+ System.out.println("PARSING ERROR: " + ex.getLocalizedMessage());
+
+ // Move onto the next command
+ currentLine = getNextCommand(inputSource, commandNumber);
+
+ continue;
+ }
+
+ // Print out parsed AST
+ System.out.println("\tParsed: " + builtAST.toString());
+
+ // Time AST transformation
+ time = System.nanoTime();
+
+ // Transform the AST
+ ITree<IDiceASTNode> transformedAST = transformAST(builtAST,
+ enviroment);
+
+ System.out.println("Command transformed in "
+ + (double) (System.nanoTime() - time) / 1000000000
+ + " s");
+
+ // Print out the transformed AST
+ System.out
+ .println("\tTransformed: " + transformedAST.toString());
+
+
+ try {
+ // Time the evaluation
+ time = System.nanoTime();
+
+ // Evaluate the expression once
+ IResult sampleResult = DiceASTEvaluator.evaluateAST(transformedAST,
+ enviroment);
+
+ System.out
+ .println(
+ "Command evaluated in "
+ + (double) (System.nanoTime()
+ - time) / 1000000000
+ + " s");
+
+ // Print out the result of evaluating the expression
+ System.out.println("\t\tSample Result: " + sampleResult);
+
+ // Update the 'last' meta-variable
+ enviroment.put("last", transformedAST);
+ } catch (UnsupportedOperationException usex) {
+ // Tell the user there was an error in evaluation
+ System.out.println("EVALUATION ERROR: " + usex.getLocalizedMessage());
+
+ // Get the next command
+ currentLine = getNextCommand(inputSource, commandNumber);
+
+ // Process it
+ continue;
+ }
+
+
+ // Increase the number of commands
+ commandNumber++;
+
+ // Get the next command
+ currentLine = getNextCommand(inputSource, commandNumber);
+ }
+
+ System.out.println("Bye.");
+
+ // Cleanup after ourselves
+ inputSource.close();
+ }
+
+ // Transform a parsed AST
+ private static ITree<IDiceASTNode> transformAST(
+ ITree<IDiceASTNode> builtAST,
+ IMap<String, ITree<IDiceASTNode>> enviroment) {
+ // Optimize the tree first
+ ITree<IDiceASTNode> optimizedTree = optimizer
+ .optimizeTree(builtAST, enviroment);
+
+ // Then, condense unnecessary operations
+ ITree<IDiceASTNode> condensedTree = OperationCondenser
+ .condense(optimizedTree);
+
+ // Next, sanitize references
+ ITree<IDiceASTNode> sanitizedTree = DiceASTReferenceSanitizer
+ .sanitize(condensedTree, enviroment);
+
+ // Re-optimize the sanitized & condensed tree
+ optimizedTree = optimizer.optimizeTree(sanitizedTree, enviroment);
+
+ // Re-condense the newly optimized tree
+ condensedTree = OperationCondenser.condense(optimizedTree);
+
+ return condensedTree;
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceASTPragma.java b/dice-lang/src/bjc/dicelang/examples/DiceASTPragma.java
new file mode 100644
index 0000000..4900e46
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceASTPragma.java
@@ -0,0 +1,22 @@
+package bjc.dicelang.examples;
+
+import java.util.function.BiConsumer;
+
+import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.funcdata.IMap;
+import bjc.utils.funcdata.ITree;
+
+import bjc.dicelang.ast.nodes.IDiceASTNode;
+
+/**
+ * Alias for the type of a 'pragma' or special language command
+ *
+ * To explain it, a pragma is a function that takes a tokenizer with the rest
+ * of the line, and an enviroment that contains variable bindings
+ * @author ben
+ *
+ */
+public interface DiceASTPragma extends
+ BiConsumer<FunctionalStringTokenizer, IMap<String, ITree<IDiceASTNode>>> {
+ // Just an alias
+}
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceExpressionParserTest.java b/dice-lang/src/bjc/dicelang/examples/DiceExpressionParserTest.java
new file mode 100644
index 0000000..b31f3a0
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceExpressionParserTest.java
@@ -0,0 +1,59 @@
+package bjc.dicelang.examples;
+
+import java.util.HashMap;
+import java.util.Scanner;
+
+import bjc.dicelang.DiceExpressionParser;
+import bjc.dicelang.IDiceExpression;
+
+/**
+ * Driver class for testing expression parser
+ *
+ * @author ben
+ *
+ */
+public class DiceExpressionParserTest {
+ /**
+ * Run the parser test
+ *
+ * @param args
+ * Unused CLI arguments
+ */
+ public static void main(String[] args) {
+ /*
+ * Get a scanner for input
+ */
+ Scanner scn = new Scanner(System.in);
+
+ /*
+ * Ask to enter a expression
+ */
+ System.out.print("Enter dice expression: ");
+
+ String exp = scn.nextLine();
+
+ /*
+ * Enter amount of times to roll an expression
+ */
+ System.out.print("Enter number of times to roll: ");
+
+ int nTimes = Integer.parseInt(scn.nextLine());
+
+ IDiceExpression dexp = DiceExpressionParser.parse(exp,
+ new HashMap<>());
+
+ /*
+ * Roll the dice a specified amount of times
+ */
+ for (int i = 1; i <= nTimes; i++) {
+ int roll = dexp.roll();
+
+ System.out.println("Rolled " + roll);
+ }
+
+ /*
+ * Clean up after ourselves
+ */
+ scn.close();
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceExpressionPreparer.java b/dice-lang/src/bjc/dicelang/examples/DiceExpressionPreparer.java
new file mode 100644
index 0000000..5488b5d
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceExpressionPreparer.java
@@ -0,0 +1,93 @@
+package bjc.dicelang.examples;
+
+import java.util.Deque;
+import java.util.LinkedList;
+
+import bjc.utils.data.IPair;
+import bjc.utils.data.Pair;
+import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.funcdata.IList;
+import bjc.utils.funcutils.ListUtils;
+import bjc.utils.parserutils.ShuntingYard;
+
+/**
+ * Prepare a dice expression to be parsed
+ *
+ * @author ben
+ *
+ */
+public class DiceExpressionPreparer {
+ /**
+ * The yard to use for shunting expressions
+ */
+ private static ShuntingYard<String> yard;
+
+ private static final int MATH_PREC = 20;
+ private static final int DICE_PREC = 10;
+ private static final int EXPR_PREC = 0;
+
+ // Do initialization for all parsers
+ static {
+ // The shunter we're going to use
+ yard = new ShuntingYard<>(false);
+
+ // Configure the shunters operators
+ // Basic mathematical operators
+ yard.addOp("+", 0 + MATH_PREC);
+ yard.addOp("-", 0 + MATH_PREC);
+
+ yard.addOp("*", 1 + MATH_PREC);
+ yard.addOp("/", 1 + MATH_PREC);
+
+ yard.addOp("d", 0 + DICE_PREC); // dice operator: use for creating
+ // variable size dice groups
+ yard.addOp("c", 1 + DICE_PREC); // compound operator: use for
+ // creating compound dice from expressions
+
+ yard.addOp("=>", 0 + EXPR_PREC); // let operator: evaluate an
+ // expression in the context of another
+ yard.addOp(":=", 1 + EXPR_PREC); // binding operator: Bind a name
+ // to a variable expression
+ }
+
+ // Prepare a command, turning raw tokens into input for the tree builder
+ public static IList<String> prepareCommand(String currentLine) {
+ // Split the command into tokens
+ IList<String> tokens = FunctionalStringTokenizer
+ .fromString(currentLine).toList();
+
+ // The linked list to use for handling tokens
+ Deque<IPair<String, String>> ops = new LinkedList<>();
+
+ // Prepare the list for operator expansion
+ ops.add(new Pair<>("+", "\\+"));
+ ops.add(new Pair<>("-", "-"));
+ ops.add(new Pair<>("*", "\\*"));
+ ops.add(new Pair<>("/", "/"));
+ ops.add(new Pair<>(":=", ":="));
+ ops.add(new Pair<>("=>", "=>"));
+
+ // Expand infix single tokens to multiple infix tokens
+ IList<String> semiExpandedTokens = ListUtils.splitTokens(tokens,
+ ops);
+
+ // Reinitialize the list
+ ops = new LinkedList<>();
+
+ // Prepare the list for deaffixation
+ ops.add(new Pair<>("(", "\\("));
+ ops.add(new Pair<>(")", "\\)"));
+ ops.add(new Pair<>("[", "\\["));
+ ops.add(new Pair<>("]", "\\]"));
+
+ // Deaffix ('s and ['s from tokens
+ IList<String> fullyExpandedTokens = ListUtils
+ .deAffixTokens(semiExpandedTokens, ops);
+
+ // Remove blank tokens
+ fullyExpandedTokens.removeIf((strang) -> strang.equals(""));
+
+ // Shunt the tokens, and hand them back
+ return yard.postfix(fullyExpandedTokens, (token) -> token);
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceLanguageState.java b/dice-lang/src/bjc/dicelang/examples/DiceLanguageState.java
new file mode 100644
index 0000000..fbb103f
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceLanguageState.java
@@ -0,0 +1,37 @@
+package bjc.dicelang.examples;
+
+import java.util.Map;
+
+import bjc.utils.data.Pair;
+
+import bjc.dicelang.DiceExpressionParser;
+import bjc.dicelang.IDiceExpression;
+
+/**
+ * Internal state of dice language
+ *
+ * @author ben
+ *
+ */
+public class DiceLanguageState
+ extends Pair<DiceExpressionParser, Map<String, IDiceExpression>> {
+
+ /**
+ * Create a new state
+ */
+ public DiceLanguageState() {
+ }
+
+ /**
+ * Create a new state with the desired parameters
+ *
+ * @param left
+ * The parser to use
+ * @param right
+ * The enviroment to use
+ */
+ public DiceLanguageState(DiceExpressionParser left,
+ Map<String, IDiceExpression> right) {
+ super(left, right);
+ }
+}
diff --git a/dice-lang/src/bjc/dicelang/examples/DiceLanguageTest.java b/dice-lang/src/bjc/dicelang/examples/DiceLanguageTest.java
new file mode 100644
index 0000000..bd6270e
--- /dev/null
+++ b/dice-lang/src/bjc/dicelang/examples/DiceLanguageTest.java
@@ -0,0 +1,96 @@
+package bjc.dicelang.examples;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.function.BiConsumer;
+
+import bjc.dicelang.DiceExpressionParser;
+import bjc.dicelang.IDiceExpression;
+
+/**
+ * Test of dice language
+ *
+ * @author ben
+ *
+ */
+public class DiceLanguageTest {
+ private static Map<String, BiConsumer<String, DiceLanguageState>> acts;
+
+ static {
+ acts = new HashMap<>();
+
+ acts.put("roll", DiceLanguageTest::rollReference);
+ acts.put("env", DiceLanguageTest::printEnv);
+ }
+
+ /**
+ * Main method
+ *
+ * @param args
+ * Unused CLI args
+ */
+ public static void main(String[] args) {
+ Scanner scn = new Scanner(System.in);
+ int i = 0;
+
+ System.out.print("dice-lang-" + i + "> ");
+ String ln = scn.nextLine();
+
+ DiceExpressionParser dep = new DiceExpressionParser();
+ Map<String, IDiceExpression> env = new HashMap<>();
+ DiceLanguageState state = new DiceLanguageState(dep, env);
+
+ while (!ln.equalsIgnoreCase("quit")) {
+ String header = ln.split(" ")[0];
+
+ if (acts.containsKey(header)) {
+ acts.get(header).accept(ln, state);
+ } else {
+ IDiceExpression exp = DiceExpressionParser.parse(ln, env);
+
+ System.out.println("\tParsed: " + exp.toString());
+ System.out.println("\tSample Roll: " + exp.roll());
+
+ env.put("last", exp);
+ }
+
+ i++;
+
+ System.out.print("dice-lang-" + i + "> ");
+ ln = scn.nextLine();
+ }
+
+ System.out.println("Bye.");
+ scn.close();
+ }
+
+ /**
+ * @param ln
+ * Unused parameter, kept to comply with expected type sig
+ */
+ private static void printEnv(String ln, DiceLanguageState stat) {
+ System.out.println("Printing enviroment for debugging purposes.");
+
+ stat.doWith((dep, env) -> env.forEach((key, exp) -> System.out
+ .println("\tKey: " + key + "\tExp: " + exp.toString())));
+ }
+
+ private static void rollReference(String ln, DiceLanguageState stat) {
+ String[] strangs = ln.split(" ");
+
+ System.out.println("\tRolling dice expression " + strangs[1] + " "
+ + strangs[2] + " times.");
+
+ int nRolls = Integer.parseInt(strangs[2]);
+
+ IDiceExpression dexp = stat
+ .merge((dep, env) -> env.get(strangs[1]));
+
+ for (int i = 1; i <= nRolls; i++) {
+ int roll = dexp.roll();
+
+ System.out.println("\tRolled " + roll);
+ }
+ }
+}