summaryrefslogtreecommitdiff
path: root/dice-lang/src/main/java/bjc
diff options
context:
space:
mode:
Diffstat (limited to 'dice-lang/src/main/java/bjc')
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java28
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ComplexDice.java8
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java8
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java8
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/Die.java5
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/OperatorDiceExpression.java (renamed from dice-lang/src/main/java/bjc/dicelang/CompoundDiceExpression.java)13
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java5
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ScalarDiceExpression.java7
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ScalarDie.java3
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java183
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java101
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java79
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java12
13 files changed, 299 insertions, 161 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java
index 94dd761..1813e97 100644
--- a/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/BindingDiceExpression.java
@@ -13,12 +13,12 @@ public class BindingDiceExpression implements IDiceExpression {
/**
* The expression being bound to a name
*/
- private IDiceExpression exp;
+ private IDiceExpression expression;
/**
* The name to bind the expression to
*/
- private String name;
+ private String variableName;
/**
* Create a new dice expression binder from two expressions and an
@@ -34,7 +34,15 @@ public class BindingDiceExpression implements IDiceExpression {
*/
public BindingDiceExpression(IDiceExpression left,
IDiceExpression right, Map<String, IDiceExpression> env) {
- this(((ReferenceDiceExpression) left).getName(), right, env);
+ if (!(left instanceof ReferenceDiceExpression)) {
+ throw new UnsupportedOperationException(
+ "Binding to non-references is unsupported."
+ + " Problematic expression is " + left);
+ } else {
+ String varName = ((ReferenceDiceExpression) left).getName();
+
+ initialize(varName, right, env);
+ }
}
/**
@@ -49,8 +57,13 @@ public class BindingDiceExpression implements IDiceExpression {
*/
public BindingDiceExpression(String name, IDiceExpression exp,
Map<String, IDiceExpression> env) {
- this.name = name;
- this.exp = exp;
+ initialize(name, exp, env);
+ }
+
+ private void initialize(String name, IDiceExpression exp,
+ Map<String, IDiceExpression> env) {
+ this.variableName = name;
+ this.expression = exp;
env.put(name, exp);
}
@@ -62,7 +75,7 @@ public class BindingDiceExpression implements IDiceExpression {
*/
@Override
public int roll() {
- return exp.roll();
+ return expression.roll();
}
/*
@@ -72,6 +85,7 @@ public class BindingDiceExpression implements IDiceExpression {
*/
@Override
public String toString() {
- return "assign[n=" + name + ", exp=" + exp.toString() + "]";
+ return "assign[n=" + variableName + ", exp="
+ + expression.toString() + "]";
}
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java b/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java
index 5d88001..054c73b 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ComplexDice.java
@@ -89,6 +89,12 @@ public class ComplexDice implements IDiceExpression {
*/
int nRoll = nDice.roll();
+ if (nRoll < 0) {
+ throw new UnsupportedOperationException(
+ "Attempted to roll a negative number of dice. "
+ + "The problematic expression is " + nDice);
+ }
+
for (int i = 0; i < nRoll; i++) {
res += die.roll();
}
@@ -110,4 +116,4 @@ public class ComplexDice implements IDiceExpression {
+ die.toString() + "]";
}
}
-}
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java
index 5ced36d..b3cc37a 100644
--- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java
+++ b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionBuilder.java
@@ -54,7 +54,7 @@ public class DiceExpressionBuilder {
* @return A new expression adding the two dice
*/
public DiceExpressionBuilder add(IDiceExpression exp) {
- baking = new CompoundDiceExpression(baking, exp, ADD);
+ baking = new OperatorDiceExpression(baking, exp, ADD);
return this;
}
@@ -87,7 +87,7 @@ public class DiceExpressionBuilder {
* @return A new expression dividing the two dice
*/
public DiceExpressionBuilder divide(IDiceExpression exp) {
- baking = new CompoundDiceExpression(baking, exp, DIVIDE);
+ baking = new OperatorDiceExpression(baking, exp, DIVIDE);
return this;
}
@@ -111,7 +111,7 @@ public class DiceExpressionBuilder {
* @return A new expression multiplying the two dice
*/
public DiceExpressionBuilder multiply(IDiceExpression exp) {
- baking = new CompoundDiceExpression(baking, exp, MULTIPLY);
+ baking = new OperatorDiceExpression(baking, exp, MULTIPLY);
return this;
}
@@ -135,7 +135,7 @@ public class DiceExpressionBuilder {
* @return A new expression adding the two dice
*/
public DiceExpressionBuilder subtract(IDiceExpression exp) {
- baking = new CompoundDiceExpression(baking, exp, SUBTRACT);
+ baking = new OperatorDiceExpression(baking, exp, SUBTRACT);
return this;
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
index 9f96835..05e8942 100644
--- a/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/DiceExpressionParser.java
@@ -96,19 +96,19 @@ public class DiceExpressionParser {
env));
break;
case "+":
- dexps.push(new CompoundDiceExpression(r, l,
+ dexps.push(new OperatorDiceExpression(r, l,
DiceExpressionType.ADD));
break;
case "-":
- dexps.push(new CompoundDiceExpression(r, l,
+ dexps.push(new OperatorDiceExpression(r, l,
DiceExpressionType.SUBTRACT));
break;
case "*":
- dexps.push(new CompoundDiceExpression(r, l,
+ dexps.push(new OperatorDiceExpression(r, l,
DiceExpressionType.MULTIPLY));
break;
case "/":
- dexps.push(new CompoundDiceExpression(r, l,
+ dexps.push(new OperatorDiceExpression(r, l,
DiceExpressionType.DIVIDE));
break;
case "c":
diff --git a/dice-lang/src/main/java/bjc/dicelang/Die.java b/dice-lang/src/main/java/bjc/dicelang/Die.java
index addc2af..c6c6ddd 100644
--- a/dice-lang/src/main/java/bjc/dicelang/Die.java
+++ b/dice-lang/src/main/java/bjc/dicelang/Die.java
@@ -26,6 +26,11 @@ public class Die implements IDiceExpression {
* The number of sides this dice has
*/
public Die(int nSides) {
+ if (nSides < 1) {
+ throw new UnsupportedOperationException(
+ "Dice with less than 1 side are not supported");
+ }
+
this.nSides = nSides;
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/CompoundDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/OperatorDiceExpression.java
index 8db481f..4ca2568 100644
--- a/dice-lang/src/main/java/bjc/dicelang/CompoundDiceExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/OperatorDiceExpression.java
@@ -6,7 +6,7 @@ package bjc.dicelang;
* @author ben
*
*/
-public class CompoundDiceExpression implements IDiceExpression {
+public class OperatorDiceExpression implements IDiceExpression {
/**
* The operator to use for combining the dice
*/
@@ -32,7 +32,7 @@ public class CompoundDiceExpression implements IDiceExpression {
* @param det
* The operator to use for combining the dices
*/
- public CompoundDiceExpression(IDiceExpression right,
+ public OperatorDiceExpression(IDiceExpression right,
IDiceExpression left, DiceExpressionType det) {
this.right = right;
this.left = left;
@@ -61,7 +61,14 @@ public class CompoundDiceExpression implements IDiceExpression {
* Round to keep results as integers. We don't really have
* any need for floating-point dice
*/
- return right.roll() / left.roll();
+ try {
+ return right.roll() / left.roll();
+ } catch (ArithmeticException aex) {
+ throw new UnsupportedOperationException(
+ "Attempted to divide by zero."
+ + " Problematic expression is "
+ + left);
+ }
default:
throw new IllegalArgumentException(
"Got passed a invalid ScalarExpressionType " + det
diff --git a/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java
index c1a4a79..27ec609 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ReferenceDiceExpression.java
@@ -51,6 +51,11 @@ public class ReferenceDiceExpression implements IDiceExpression {
*/
@Override
public int roll() {
+ if (!env.containsKey(name)) {
+ throw new UnsupportedOperationException(
+ "Attempted to reference undefined variable " + name);
+ }
+
return env.get(name).roll();
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ScalarDiceExpression.java b/dice-lang/src/main/java/bjc/dicelang/ScalarDiceExpression.java
index be0cbb6..03b2f83 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ScalarDiceExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ScalarDiceExpression.java
@@ -54,7 +54,12 @@ public class ScalarDiceExpression implements IDiceExpression {
case MULTIPLY:
return exp.roll() * scalar;
case DIVIDE:
- return exp.roll() / scalar;
+ try {
+ return exp.roll() / scalar;
+ } catch (ArithmeticException aex) {
+ throw new UnsupportedOperationException(
+ "Attempted to divide by zero.");
+ }
default:
throw new IllegalStateException(
"Got passed a invalid ScalarExpressionType "
diff --git a/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java b/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java
index 8078e8b..fbdfb7e 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ScalarDie.java
@@ -41,5 +41,4 @@ public class ScalarDie implements IDiceExpression {
public String toString() {
return Integer.toString(num);
}
-
-}
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
index 078c952..eaadc53 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTExpression.java
@@ -2,6 +2,8 @@ package bjc.dicelang.ast;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.Function;
+
import org.apache.commons.lang3.StringUtils;
import bjc.dicelang.ComplexDice;
@@ -20,6 +22,21 @@ import bjc.utils.parserutils.AST;
*/
public class DiceASTExpression implements IDiceExpression {
+ private static final class VariableRetriever
+ implements Function<IDiceASTNode, String> {
+ @Override
+ public String apply(IDiceASTNode node) {
+ if (node.getType() != DiceASTType.VARIABLE) {
+ throw new UnsupportedOperationException(
+ "Attempted to assign to something that isn't a variable."
+ + " This isn't supported yet. The problem node is "
+ + node);
+ }
+
+ return ((VariableDiceNode) node).getVariable();
+ }
+ }
+
/**
* Build the map of operations to use when collapsing the AST
*
@@ -44,69 +61,104 @@ public class DiceASTExpression implements IDiceExpression {
});
operatorCollapsers.put(OperatorDiceNode.SUBTRACT,
- (left, right) -> {
- return left.merge(
- (lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval - rval,
- new AST<>(
- OperatorDiceNode.SUBTRACT,
- last, rast));
- }));
-
+ (leftNode, rightNode) -> {
+ return leftNode.merge((leftValue, leftAST) -> {
+ return rightNode.merge((rightValue, rightAST) -> {
+ return new Pair<>(leftValue - rightValue,
+ new AST<>(OperatorDiceNode.SUBTRACT,
+ leftAST, rightAST));
+ });
+ });
});
+
operatorCollapsers.put(OperatorDiceNode.MULTIPLY,
- (left, right) -> {
- return left.merge(
- (lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval * rval,
- new AST<>(
- OperatorDiceNode.MULTIPLY,
- last, rast));
- }));
+ (leftNode, rightNode) -> {
+ return leftNode.merge((leftValue, leftAST) -> {
+ return rightNode.merge((rightValue, rightAST) -> {
+ return new Pair<>(leftValue * rightValue,
+ new AST<>(OperatorDiceNode.MULTIPLY,
+ leftAST, rightAST));
+ });
+ });
});
- operatorCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(lval / rval,
- new AST<>(OperatorDiceNode.DIVIDE, last, rast));
- }));
- });
+ operatorCollapsers.put(OperatorDiceNode.DIVIDE,
+ (leftNode, rightNode) -> {
+ return leftNode.merge((leftValue, leftAST) -> {
+ return rightNode.merge((rightValue, rightAST) -> {
+ if (rightValue == 0) {
+ throw new ArithmeticException(
+ "Attempted to divide by zero. The AST of the problem expression is "
+ + rightAST);
+ }
+
+ return new Pair<>(leftValue / rightValue,
+ new AST<>(OperatorDiceNode.DIVIDE,
+ leftAST, rightAST));
+ });
+ });
+ });
operatorCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- String nam = last.collapse((nod) -> {
- return ((VariableDiceNode) nod).getVariable();
- }, (v) -> (lv, rv) -> null, (r) -> r);
+ return left.merge((leftValue, leftAST) -> {
+ return right.merge((rightValue, rightAST) -> {
+ String variableName = leftAST.collapse(
+ new VariableRetriever(), (operator) -> {
+ throw new UnsupportedOperationException(
+ "Can only assign to plain variable names. The problem operator is "
+ + operator);
+ }, (returnedAST) -> returnedAST);
- enviroment.put(nam,
- new DiceASTExpression(rast, enviroment));
+ enviroment.put(variableName,
+ new DiceASTExpression(rightAST, enviroment));
- return new Pair<>(rval,
- new AST<>(OperatorDiceNode.ASSIGN, last, rast));
- }));
+ return new Pair<>(rightValue, new AST<>(
+ OperatorDiceNode.ASSIGN, leftAST, rightAST));
+ });
+ });
});
operatorCollapsers.put(OperatorDiceNode.COMPOUND,
- (left, right) -> {
- return left.merge(
- (lval, last) -> right.merge((rval, rast) -> {
- int ival = Integer
- .parseInt(Integer.toString(lval)
- + Integer.toString(rval));
-
- return new Pair<>(ival,
- new AST<>(
- OperatorDiceNode.COMPOUND,
- last, rast));
- }));
+ (leftNode, rightNode) -> {
+ return leftNode.merge((leftValue, leftAST) -> {
+ return rightNode.merge((rightValue, rightAST) -> {
+ int compoundValue = Integer.parseInt(
+ Integer.toString(leftValue) + Integer
+ .toString(rightValue));
+
+ return new Pair<>(compoundValue,
+ new AST<>(OperatorDiceNode.COMPOUND,
+ leftAST, rightAST));
+ });
+ });
});
- operatorCollapsers.put(OperatorDiceNode.GROUP, (left, right) -> {
- return left.merge((lval, last) -> right.merge((rval, rast) -> {
- return new Pair<>(new ComplexDice(lval, rval).roll(),
- new AST<>(OperatorDiceNode.GROUP, last, rast));
- }));
- });
+ operatorCollapsers.put(OperatorDiceNode.GROUP,
+ (leftNode, rightNode) -> {
+ return leftNode.merge((leftValue, leftAST) -> {
+ return rightNode.merge((rightValue, rightAST) -> {
+ if (leftValue < 0) {
+ throw new UnsupportedOperationException(
+ "Can't attempt to roll a negative number of dice."
+ + " The problematic AST is "
+ + leftAST);
+ } else if (rightValue < 1) {
+ throw new UnsupportedOperationException(
+ "Can't roll dice with less than one side."
+ + " The problematic AST is "
+ + rightAST);
+ }
+
+ int rolledValue =
+ new ComplexDice(leftValue, rightValue)
+ .roll();
+
+ return new Pair<>(rolledValue,
+ new AST<>(OperatorDiceNode.GROUP,
+ leftAST, rightAST));
+ });
+ });
+ });
return operatorCollapsers;
}
@@ -144,7 +196,7 @@ public class DiceASTExpression implements IDiceExpression {
* represents
*/
private Pair<Integer, AST<IDiceASTNode>> evalLeaf(IDiceASTNode tokn) {
- if (tokn instanceof VariableDiceNode) {
+ if (tokn.getType() == DiceASTType.VARIABLE) {
String varName = ((VariableDiceNode) tokn).getVariable();
if (env.containsKey(varName)) {
@@ -154,25 +206,37 @@ public class DiceASTExpression implements IDiceExpression {
// Handle special case for defining variables
return new Pair<>(0, new AST<>(tokn));
}
- } else {
- LiteralDiceNode lnod = (LiteralDiceNode) tokn;
- String dat = lnod.getData();
+ } else if (tokn.getType() == DiceASTType.LITERAL) {
+ LiteralDiceNode literalNode = (LiteralDiceNode) tokn;
+ String dat = literalNode.getData();
if (StringUtils.countMatches(dat, 'c') == 1
- && !dat.equalsIgnoreCase("c")) {
+ && !dat.equalsIgnoreCase("c")
+ && !dat.startsWith("c")) {
String[] strangs = dat.split("c");
+
return new Pair<>(new CompoundDice(strangs).roll(),
new AST<>(tokn));
} else if (StringUtils.countMatches(dat, 'd') == 1
- && !dat.equalsIgnoreCase("d")) {
+ && !dat.equalsIgnoreCase("d")
+ && !dat.startsWith("d")) {
/*
* Handle dice groups
*/
return new Pair<>(ComplexDice.fromString(dat).roll(),
new AST<>(tokn));
} else {
- return new Pair<>(Integer.parseInt(dat), new AST<>(tokn));
+ try {
+ return new Pair<>(Integer.parseInt(dat),
+ new AST<>(tokn));
+ } catch (NumberFormatException nfex) {
+ throw new UnsupportedOperationException(
+ "Found malformed leaf token " + tokn);
+ }
}
+ } else {
+ throw new UnsupportedOperationException("Found leaf operator "
+ + tokn + ". These aren't supported.");
}
}
@@ -196,7 +260,8 @@ public class DiceASTExpression implements IDiceExpression {
buildOperations(env);
return ast.collapse(this::evalLeaf, operations::get,
- (r) -> r.merge((left, right) -> left));
+ (returnedValue) -> returnedValue
+ .merge((left, right) -> left));
}
/*
@@ -208,4 +273,4 @@ public class DiceASTExpression implements IDiceExpression {
public String toString() {
return ast.toString();
}
-}
+} \ No newline at end of file
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java
index aa15c4d..fad4870 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTFlattener.java
@@ -3,17 +3,19 @@ package bjc.dicelang.ast;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BinaryOperator;
+import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
import bjc.dicelang.BindingDiceExpression;
import bjc.dicelang.ComplexDice;
import bjc.dicelang.CompoundDice;
-import bjc.dicelang.CompoundDiceExpression;
+import bjc.dicelang.OperatorDiceExpression;
import bjc.dicelang.DiceExpressionType;
import bjc.dicelang.IDiceExpression;
import bjc.dicelang.ReferenceDiceExpression;
import bjc.dicelang.ScalarDie;
+
import bjc.utils.parserutils.AST;
/**
@@ -24,6 +26,60 @@ import bjc.utils.parserutils.AST;
*
*/
public class DiceASTFlattener {
+ private static final class NodeCollapser
+ implements Function<IDiceASTNode, IDiceExpression> {
+ private Map<String, IDiceExpression> enviroment;
+
+ public NodeCollapser(Map<String, IDiceExpression> env) {
+ this.enviroment = env;
+ }
+
+ @Override
+ public IDiceExpression apply(IDiceASTNode nod) {
+ if (nod.getType() == DiceASTType.LITERAL) {
+ return expFromLiteral((LiteralDiceNode) nod);
+ } else if (nod.getType() == DiceASTType.VARIABLE) {
+ String varName = ((VariableDiceNode) nod).getVariable();
+
+ return new ReferenceDiceExpression(varName, enviroment);
+ } else {
+ throw new UnsupportedOperationException(
+ "Attempted to flatten something that can't be"
+ + " flattened. The culprit is " + nod);
+ }
+ }
+
+ /**
+ * Create a dice expression from a literal token
+ *
+ * @param tok
+ * The token to convert to an expression
+ * @return The dice expression represented by the token
+ */
+ private static IDiceExpression
+ expFromLiteral(LiteralDiceNode tok) {
+ String data = tok.getData();
+
+ if (data.equals("")) {
+ throw new UnsupportedOperationException(
+ "Can't convert a blank token into a literal");
+ }
+
+ if (StringUtils.countMatches(data, 'c') == 1
+ && !data.equalsIgnoreCase("c")) {
+ String[] strangs = data.split("c");
+
+ return new CompoundDice(ComplexDice.fromString(strangs[0]),
+ ComplexDice.fromString(strangs[1]));
+ } else if (StringUtils.countMatches(data, 'd') == 1
+ && !data.equalsIgnoreCase("d")) {
+ return ComplexDice.fromString(data);
+ } else {
+ return new ScalarDie(Integer.parseInt(data));
+ }
+ }
+ }
+
/**
* Build the operations to use for tree flattening
*
@@ -35,20 +91,21 @@ public class DiceASTFlattener {
buildOperations(Map<String, IDiceExpression> env) {
Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers =
new HashMap<>();
+
opCollapsers.put(OperatorDiceNode.ADD, (left, right) -> {
- return new CompoundDiceExpression(right, left,
+ return new OperatorDiceExpression(right, left,
DiceExpressionType.ADD);
});
opCollapsers.put(OperatorDiceNode.SUBTRACT, (left, right) -> {
- return new CompoundDiceExpression(right, left,
+ return new OperatorDiceExpression(right, left,
DiceExpressionType.SUBTRACT);
});
opCollapsers.put(OperatorDiceNode.MULTIPLY, (left, right) -> {
- return new CompoundDiceExpression(right, left,
+ return new OperatorDiceExpression(right, left,
DiceExpressionType.MULTIPLY);
});
opCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
- return new CompoundDiceExpression(right, left,
+ return new OperatorDiceExpression(right, left,
DiceExpressionType.DIVIDE);
});
opCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> {
@@ -65,30 +122,6 @@ public class DiceASTFlattener {
}
/**
- * Create a dice expression from a literal token
- *
- * @param tok
- * The token to convert to an expression
- * @return The dice expression represented by the token
- */
- private static IDiceExpression expFromLiteral(LiteralDiceNode tok) {
- String data = tok.getData();
-
- if (StringUtils.countMatches(data, 'c') == 1
- && !data.equalsIgnoreCase("c")) {
- String[] strangs = data.split("c");
-
- return new CompoundDice(ComplexDice.fromString(strangs[0]),
- ComplexDice.fromString(strangs[1]));
- } else if (StringUtils.countMatches(data, 'd') == 1
- && !data.equalsIgnoreCase("d")) {
- return ComplexDice.fromString(data);
- } else {
- return new ScalarDie(Integer.parseInt(data));
- }
- }
-
- /**
* Flatten a AST into a dice expression
*
* @param ast
@@ -102,13 +135,7 @@ public class DiceASTFlattener {
Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers =
buildOperations(env);
- return ast.collapse((nod) -> {
- if (nod instanceof LiteralDiceNode) {
- return expFromLiteral((LiteralDiceNode) nod);
- } else {
- return new ReferenceDiceExpression(
- ((VariableDiceNode) nod).getVariable(), env);
- }
- } , opCollapsers::get, (r) -> r);
+ return ast.collapse(new NodeCollapser(env), opCollapsers::get,
+ (r) -> r);
}
}
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
index d0b970a..67d2d50 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java
@@ -2,6 +2,7 @@ package bjc.dicelang.ast;
import java.util.Deque;
import java.util.LinkedList;
+import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
@@ -20,6 +21,44 @@ import bjc.utils.parserutils.TreeConstructor;
*
*/
public class DiceASTParser {
+ private static final class NodeBaker
+ implements Function<String, IDiceASTNode> {
+ @Override
+ public IDiceASTNode apply(String tok) {
+ if (isOperator(tok)) {
+ return OperatorDiceNode.fromString(tok);
+ } else if (NodeBaker.isLiteral(tok)) {
+ return new LiteralDiceNode(tok);
+ } else {
+ return new VariableDiceNode(tok);
+ }
+ }
+
+ /**
+ * Check if a token represents a literal
+ *
+ * @param tok
+ * The token to check
+ * @return Whether or not the token represents a literal
+ */
+ private static boolean isLiteral(String tok) {
+ if (StringUtils.countMatches(tok, 'c') == 1
+ && !tok.equalsIgnoreCase("c")) {
+ return true;
+ } else if (StringUtils.countMatches(tok, 'd') == 1
+ && !tok.equalsIgnoreCase("d")) {
+ return true;
+ } else {
+ try {
+ Integer.parseInt(tok);
+ return true;
+ } catch (NumberFormatException nfx) {
+ return false;
+ }
+ }
+ }
+ }
+
/**
* The yard to use for shunting expressions
*/
@@ -45,7 +84,7 @@ public class DiceASTParser {
*/
public AST<IDiceASTNode> buildAST(String exp) {
FunctionalList<String> tokens =
- FunctionalStringTokenizer.fromString(exp).toList((s) -> s);
+ FunctionalStringTokenizer.fromString(exp).toList();
Deque<Pair<String, String>> ops = new LinkedList<>();
@@ -70,53 +109,21 @@ public class DiceASTParser {
yard.postfix(fullyExpandedTokens, (s) -> s);
AST<String> rawAST = TreeConstructor.constructTree(shunted,
- this::isOperator, (op) -> false, null);
+ DiceASTParser::isOperator);
- AST<IDiceASTNode> bakedAST = rawAST.transmuteAST((tok) -> {
- if (isOperator(tok)) {
- return OperatorDiceNode.fromString(tok);
- } else if (isLiteral(tok)) {
- return new LiteralDiceNode(tok);
- } else {
- return new VariableDiceNode(tok);
- }
- });
+ AST<IDiceASTNode> bakedAST = rawAST.transmuteAST(new NodeBaker());
return bakedAST;
}
/**
- * Check if a token represents a literal
- *
- * @param tok
- * The token to check
- * @return Whether or not the token represents a literal
- */
- private static boolean isLiteral(String tok) {
- if (StringUtils.countMatches(tok, 'c') == 1
- && !tok.equalsIgnoreCase("c")) {
- return true;
- } else if (StringUtils.countMatches(tok, 'd') == 1
- && !tok.equalsIgnoreCase("d")) {
- return true;
- } else {
- try {
- Integer.parseInt(tok);
- return true;
- } catch (NumberFormatException nfx) {
- return false;
- }
- }
- }
-
- /**
* Check if a token represents an operator
*
* @param tok
* The token to check if it represents an operator
* @return Whether or not the token represents an operator
*/
- private boolean isOperator(String tok) {
+ private static boolean isOperator(String tok) {
switch (tok) {
case ":=":
case "+":
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
index aaabe8b..a74d61e 100644
--- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
+++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java
@@ -23,8 +23,7 @@ public final class DiceASTReferenceChecker
* Create a new reference checker
*
* @param referencesVar
- * The holder of whether the variable is referenced or
- * not
+ * The holder of whether the variable is referenced or not
* @param varName
* The variable to check for references in
*/
@@ -37,21 +36,20 @@ public final class DiceASTReferenceChecker
@Override
public void accept(IDiceASTNode astNode) {
if (!referencesVariable.unwrap(bool -> bool)) {
- if (isDirectReferenceToLast(astNode)) {
+ if (isDirectReference(astNode)) {
referencesVariable.transform((bool) -> false);
}
}
}
/**
- * Check if a given AST node directly references the meta-variable
- * last
+ * Check if a given AST node directly references the specified variable
*
* @param astNode
* The node to check
- * @return Whether or not the node directly references last
+ * @return Whether or not the node directly the variable
*/
- private boolean isDirectReferenceToLast(IDiceASTNode astNode) {
+ private boolean isDirectReference(IDiceASTNode astNode) {
if (astNode.getType() == DiceASTType.VARIABLE) {
VariableDiceNode node = (VariableDiceNode) astNode;