summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/utils/dice/DiceExpressionParser.java
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-03-28 08:44:54 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-03-28 08:44:54 -0400
commit78d9c539e25f16fd15f06c2b2c48c0ad37a21540 (patch)
tree52d5db559d390c2fb83d4a4cd3bbfa4344c482e8 /dice-lang/src/bjc/utils/dice/DiceExpressionParser.java
parent1a020352bdcbb6b5279b703f93e42a1eb7071e36 (diff)
Imported dice stuff from general utils into dedicated project
Diffstat (limited to 'dice-lang/src/bjc/utils/dice/DiceExpressionParser.java')
-rw-r--r--dice-lang/src/bjc/utils/dice/DiceExpressionParser.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/dice-lang/src/bjc/utils/dice/DiceExpressionParser.java b/dice-lang/src/bjc/utils/dice/DiceExpressionParser.java
new file mode 100644
index 0000000..4113be4
--- /dev/null
+++ b/dice-lang/src/bjc/utils/dice/DiceExpressionParser.java
@@ -0,0 +1,152 @@
+package bjc.utils.dice;
+
+import java.util.Map;
+import java.util.Stack;
+
+import org.apache.commons.lang3.StringUtils;
+
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.FunctionalStringTokenizer;
+import bjc.utils.parserutils.ShuntingYard;
+
+/**
+ * Parse a dice expression from a string
+ *
+ * @author ben
+ *
+ */
+public class DiceExpressionParser {
+ /**
+ * Parse a dice expression from a string
+ *
+ * @param exp
+ * The string to parse an expression from
+ * @param env
+ * The enviroment to use when parsing expressions
+ * @return The parsed dice expression
+ */
+ public IDiceExpression parse(String exp,
+ Map<String, IDiceExpression> env) {
+ /*
+ * Create a tokenizer over the strings
+ */
+ FunctionalStringTokenizer fst = new FunctionalStringTokenizer(exp);
+
+ /*
+ * Create a shunter to rewrite the expression
+ */
+ ShuntingYard<String> yard = new ShuntingYard<>();
+
+ /*
+ * Add our custom operators to the yard
+ */
+ yard.addOp("d", 5); // dice operator: use for creating variable
+ // size dice groups
+ yard.addOp("c", 6); // compound operator: use for creating compound
+ // dice from expressions
+ yard.addOp(":=", 0); // binding operator: Bind a name to a variable
+ // expression
+
+ /*
+ * Shunt the expression to postfix form
+ */
+ FunctionalList<String> ls =
+ yard.postfix(fst.toList(s -> s), s -> s);
+
+ /*
+ * Create a stack for building an expression from parts
+ */
+ Stack<IDiceExpression> dexps = new Stack<>();
+
+ /*
+ * Create the expression from parts
+ */
+ ls.forEach((tok) -> {
+ /*
+ * Handle compound dice
+ */
+ if (StringUtils.countMatches(tok, 'c') == 1
+ && !tok.equalsIgnoreCase("c")) {
+ String[] strangs = tok.split("c");
+
+ dexps.push(new CompoundDice(strangs));
+ } else if (StringUtils.countMatches(tok, 'd') == 1
+ && !tok.equalsIgnoreCase("d")) {
+ /*
+ * Handle dice groups
+ */
+ dexps.push(ComplexDice.fromString(tok));
+ } else {
+ try {
+ /*
+ * Handle scalar numbers
+ */
+ dexps.push(new ScalarDie(Integer.parseInt(tok)));
+ } catch (NumberFormatException nfex) {
+
+ if (dexps.size() >= 2) {
+ /*
+ * Apply an operation to two dice
+ */
+ IDiceExpression r = dexps.pop();
+ IDiceExpression l = dexps.pop();
+ switch (tok) {
+ case ":=":
+ dexps.push(new BindingDiceExpression(l, r,
+ env));
+ break;
+ case "+":
+ dexps.push(new CompoundDiceExpression(r, l,
+ DiceExpressionType.ADD));
+ break;
+ case "-":
+ dexps.push(new CompoundDiceExpression(r, l,
+ DiceExpressionType.SUBTRACT));
+ break;
+ case "*":
+ dexps.push(new CompoundDiceExpression(r, l,
+ DiceExpressionType.MULTIPLY));
+ break;
+ case "/":
+ dexps.push(new CompoundDiceExpression(r, l,
+ DiceExpressionType.DIVIDE));
+ break;
+ case "c":
+ dexps.push(new CompoundDice(l, r));
+ break;
+ case "d":
+ dexps.push(new ComplexDice(l, r));
+ break;
+ default:
+ /*
+ * Parse it as a variable reference
+ *
+ * Make sure to restore popped variables
+ */
+ dexps.push(l);
+ dexps.push(r);
+
+ dexps.push(new ReferenceDiceExpression(tok,
+ env));
+ }
+ } else {
+ /*
+ * Parse it as a variable reference
+ */
+ dexps.push(new ReferenceDiceExpression(tok, env));
+ }
+ }
+ }
+ });
+
+ if (dexps.size() != 1) {
+ System.err.println(
+ "WARNING: Leftovers found on dice expression stack. Remember, := is assignment.");
+ }
+
+ /*
+ * Return the built expression
+ */
+ return dexps.pop();
+ }
+}