diff options
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils/dice/ast')
8 files changed, 367 insertions, 111 deletions
diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTExpression.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTExpression.java index 3b81888..aceeed0 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTExpression.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTExpression.java @@ -12,48 +12,22 @@ import bjc.utils.dice.CompoundDice; import bjc.utils.dice.IDiceExpression; import bjc.utils.parserutils.AST; +/** + * An implementation of {@link IDiceExpression} backed by an AST of + * {@link IDiceASTNode}s + * + * @author ben + * + */ public class DiceASTExpression implements IDiceExpression { - private AST<IDiceASTNode> ast; - private Map<String, DiceASTExpression> env; - - public DiceASTExpression(AST<IDiceASTNode> ast, - Map<String, DiceASTExpression> env) { - this.ast = ast; - this.env = env; - } - - private Pair<Integer, AST<IDiceASTNode>> evalLeaf(IDiceASTNode tokn) { - if (tokn instanceof VariableDiceNode) { - String varName = ((VariableDiceNode) tokn).getVariable(); - - if (env.containsKey(varName)) { - return new Pair<>(env.get(varName).roll(), new AST<>(tokn)); - } else { - // Handle special case for defining variables - return new Pair<>(0, new AST<>(tokn)); - } - } else { - LiteralDiceNode lnod = (LiteralDiceNode) tokn; - String dat = lnod.getData(); - - if (StringUtils.countMatches(dat, 'c') == 1 - && !dat.equalsIgnoreCase("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")) { - /* - * Handle dice groups - */ - return new Pair<>(ComplexDice.fromString(dat).roll(), - new AST<>(tokn)); - } else { - return new Pair<>(Integer.parseInt(dat), new AST<>(tokn)); - } - } - } + /** + * Build the map of operations to use when collapsing the AST + * + * @param env + * The enviroment to evaluate bindings and such against + * @return The operations to use when collapsing the AST + */ private static Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> buildOperations(Map<String, DiceASTExpression> env) { @@ -121,6 +95,83 @@ public class DiceASTExpression implements IDiceExpression { return opCollapsers; } + /** + * The AST this expression will evaluate + */ + private AST<IDiceASTNode> ast; + + /** + * The enviroment to evaluate bindings and such against + */ + private Map<String, DiceASTExpression> env; + + /** + * Create a new dice expression backed by an AST + * + * @param ast + * The AST backing this expression + * @param env + * The enviroment to evaluate bindings against + */ + public DiceASTExpression(AST<IDiceASTNode> ast, + Map<String, DiceASTExpression> env) { + this.ast = ast; + this.env = env; + } + + /** + * Expand a leaf AST token into a pair for evaluation + * + * @param tokn + * The token to evaluate + * @return A pair consisting of the token's value and the AST it + * represents + */ + private Pair<Integer, AST<IDiceASTNode>> evalLeaf(IDiceASTNode tokn) { + if (tokn instanceof VariableDiceNode) { + String varName = ((VariableDiceNode) tokn).getVariable(); + + if (env.containsKey(varName)) { + return new Pair<>(env.get(varName).roll(), + new AST<>(tokn)); + } else { + // Handle special case for defining variables + return new Pair<>(0, new AST<>(tokn)); + } + } else { + LiteralDiceNode lnod = (LiteralDiceNode) tokn; + String dat = lnod.getData(); + + if (StringUtils.countMatches(dat, 'c') == 1 + && !dat.equalsIgnoreCase("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")) { + /* + * Handle dice groups + */ + return new Pair<>(ComplexDice.fromString(dat).roll(), + new AST<>(tokn)); + } else { + return new Pair<>(Integer.parseInt(dat), new AST<>(tokn)); + } + } + } + + /** + * Get the AST bound to this expression + * @return the ast + */ + public AST<IDiceASTNode> getAst() { + return ast; + } + + /* + * (non-Javadoc) + * @see bjc.utils.dice.IDiceExpression#roll() + */ @Override public int roll() { Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> operations = @@ -130,15 +181,12 @@ public class DiceASTExpression implements IDiceExpression { (r) -> r.merge((left, right) -> left)); } + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ @Override public String toString() { return ast.toString(); } - - /** - * @return the ast - */ - public AST<IDiceASTNode> getAst() { - return ast; - } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFlattener.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFlattener.java index da402c3..70465a5 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFlattener.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFlattener.java @@ -16,25 +16,25 @@ import bjc.utils.dice.ReferenceDiceExpression; import bjc.utils.dice.ScalarDie; import bjc.utils.parserutils.AST; +/** + * Flatten an {@link AST} of {@link IDiceASTNode} into a + * {@link IDiceExpression} + * + * @author ben + * + */ public class DiceASTFlattener { - public static IDiceExpression flatten(AST<IDiceASTNode> ast, - Map<String, IDiceExpression> env) { - 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); - } - - private static Map<IDiceASTNode, BinaryOperator<IDiceExpression>> buildOperations( - Map<String, IDiceExpression> env) { - Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers = new HashMap<>(); + /** + * Build the operations to use for tree flattening + * + * @param env + * The enviroment the tree will be flattened against + * @return The operations needed for tree flattening + */ + private static Map<IDiceASTNode, BinaryOperator<IDiceExpression>> + buildOperations(Map<String, IDiceExpression> env) { + Map<IDiceASTNode, BinaryOperator<IDiceExpression>> opCollapsers = + new HashMap<>(); opCollapsers.put(OperatorDiceNode.ADD, (left, right) -> { return new CompoundDiceExpression(right, left, DiceExpressionType.ADD); @@ -64,6 +64,13 @@ public class DiceASTFlattener { return opCollapsers; } + /** + * 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(); @@ -80,4 +87,28 @@ public class DiceASTFlattener { return new ScalarDie(Integer.parseInt(data)); } } + + /** + * Flatten a AST into a dice expression + * + * @param ast + * The AST to flatten + * @param env + * The enviroment to flatten against + * @return The AST, flattened into a dice expression + */ + public static IDiceExpression flatten(AST<IDiceASTNode> ast, + Map<String, IDiceExpression> env) { + 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); + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFreezer.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFreezer.java index 04cc99b..efe37c0 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFreezer.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFreezer.java @@ -4,7 +4,52 @@ import java.util.Map; import bjc.utils.parserutils.AST; +/** + * Freeze references in a dice AST, replacing variable references with what + * the variables refer to + * + * @author ben + * + */ public class DiceASTFreezer { + /** + * Expand a reference + * + * @param vnode + * The node containing the reference to expand + * @param env + * The enviroment to expand against + * @return The expanded reference + */ + private static AST<IDiceASTNode> expandNode(VariableDiceNode vnode, + Map<String, AST<IDiceASTNode>> env) { + return env.get(vnode.getVariable()); + } + + /** + * Expand a reference + * + * @param vnode + * The node containing the reference to expand + * @param env + * The enviroment to expand against + * @return The expanded reference + */ + private static AST<IDiceASTNode> expandNode2(VariableDiceNode vnode, + Map<String, DiceASTExpression> env) { + return env.get(vnode.getVariable()).getAst(); + } + + /** + * Freeze the references in an AST + * + * @param tree + * The tree to freeze references in + * @param env + * The enviroment to get reference values from + * @return The tree with references frozen + */ + @SuppressWarnings("unused") public static AST<IDiceASTNode> freezeAST(AST<IDiceASTNode> tree, Map<String, AST<IDiceASTNode>> env) { return tree.collapse((nod) -> { @@ -20,6 +65,16 @@ public class DiceASTFreezer { } , (r) -> r); } + /** + * Freeze the references in an expression backed by an AST + * + * @param tree + * The tree-backed expression to freeze references in + * @param env + * The enviroment to get reference values from + * @return The tree with references frozen + */ + @SuppressWarnings("unused") public static AST<IDiceASTNode> freezeAST(DiceASTExpression tree, Map<String, DiceASTExpression> env) { return tree.getAst().collapse((nod) -> { @@ -34,14 +89,4 @@ public class DiceASTFreezer { return new AST<IDiceASTNode>(op, left, right); } , (r) -> r); } - - private static AST<IDiceASTNode> expandNode(VariableDiceNode vnode, - Map<String, AST<IDiceASTNode>> env) { - return env.get(vnode.getVariable()); - } - - private static AST<IDiceASTNode> expandNode2(VariableDiceNode vnode, - Map<String, DiceASTExpression> env) { - return env.get(vnode.getVariable()).getAst(); - } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTParser.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTParser.java index d56ad0e..b25f5b4 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTParser.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTParser.java @@ -8,7 +8,16 @@ import bjc.utils.parserutils.AST; import bjc.utils.parserutils.ShuntingYard; import bjc.utils.parserutils.TreeConstructor; +/** + * Create an AST from a string expression + * + * @author ben + * + */ public class DiceASTParser { + /** + * The yard to use for shunting expressions + */ private static ShuntingYard<String> yard; static { @@ -22,14 +31,21 @@ public class DiceASTParser { // expression } + /** + * Build an AST from a string expression + * + * @param exp + * The string to build from + * @return An AST built from the passed in string + */ public AST<IDiceASTNode> buildAST(String exp) { - FunctionalList<String> tokens = FunctionalStringTokenizer - .fromString(exp).toList((s) -> s); + FunctionalList<String> tokens = + FunctionalStringTokenizer.fromString(exp).toList((s) -> s); FunctionalList<String> shunted = yard.postfix(tokens, (s) -> s); - AST<String> rawAST = TreeConstructor.constructTree(shunted, - this::isOperator); + AST<String> rawAST = + TreeConstructor.constructTree(shunted, this::isOperator); AST<IDiceASTNode> bakedAST = rawAST.transmuteAST((tok) -> { if (isOperator(tok)) { @@ -44,22 +60,14 @@ public class DiceASTParser { return bakedAST; } - private boolean isOperator(String tok) { - switch (tok) { - case ":=": - case "+": - case "-": - case "*": - case "/": - case "c": - case "d": - return true; - default: - return false; - } - } - - private boolean isLiteral(String 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; @@ -75,4 +83,26 @@ public class DiceASTParser { } } } + + /** + * 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) { + switch (tok) { + case ":=": + case "+": + case "-": + case "*": + case "/": + case "c": + case "d": + return true; + default: + return false; + } + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/IDiceASTNode.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/IDiceASTNode.java index 3fb14fe..073da89 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/IDiceASTNode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/IDiceASTNode.java @@ -1,5 +1,16 @@ package bjc.utils.dice.ast; +/** + * The interface for a node in a dice AST + * + * @author ben + * + */ public interface IDiceASTNode { + /** + * Check if this node represents an operator or not + * + * @return Whether or not this node represents an operator + */ public boolean isOperator(); } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java index 20358fb..b0c1400 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java @@ -1,8 +1,23 @@ package bjc.utils.dice.ast; +/** + * A AST node that represents a literal value + * + * @author ben + * + */ public class LiteralDiceNode implements IDiceASTNode { + /** + * The value contained by this node + */ private String data; + /** + * Create a new node with the given value + * + * @param data + * The value to be in this node + */ public LiteralDiceNode(String data) { this.data = data; } @@ -20,7 +35,12 @@ public class LiteralDiceNode implements IDiceASTNode { public String getData() { return data; } - + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ @Override public String toString() { return data; diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/OperatorDiceNode.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/OperatorDiceNode.java index 92b49b7..c4f7763 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/OperatorDiceNode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/OperatorDiceNode.java @@ -4,16 +4,51 @@ package bjc.utils.dice.ast; // 1. DiceASTExpression // 2. DiceASTFlattener // 3. DiceASTParser +/** + * A node that represents an operator + * + * @author ben + * + */ public enum OperatorDiceNode implements IDiceASTNode { - ASSIGN, ADD, SUBTRACT, MULTIPLY, DIVIDE, GROUP, COMPOUND; - - @Override - public boolean isOperator() { - return true; - } - + /** + * Represents adding two nodes + */ + ADD, + /** + * Represents assigning one node to another + */ + ASSIGN, + /** + * Representings combining two node values together + */ + COMPOUND, + /** + * Represents dividing two nodes + */ + DIVIDE, + /** + * Represents using one node a variable number of times + */ + GROUP, + /** + * Represents multiplying two nodes + */ + MULTIPLY, + /** + * Represents subtracting two nodes + */ + SUBTRACT; + + /** + * Create a operator node from a string + * + * @param s + * The string to convert to a node + * @return The operator corresponding to the node + */ public static OperatorDiceNode fromString(String s) { - switch(s) { + switch (s) { case ":=": return ASSIGN; case "+": @@ -29,7 +64,18 @@ public enum OperatorDiceNode implements IDiceASTNode { case "c": return COMPOUND; default: - throw new IllegalArgumentException(s + " is not a valid operator node"); + throw new IllegalArgumentException( + s + " is not a valid operator node"); } } + + /* + * (non-Javadoc) + * + * @see bjc.utils.dice.ast.IDiceASTNode#isOperator() + */ + @Override + public boolean isOperator() { + return true; + } } diff --git a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/VariableDiceNode.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/VariableDiceNode.java index 6ae3189..43a09b2 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/dice/ast/VariableDiceNode.java +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/VariableDiceNode.java @@ -1,17 +1,27 @@ package bjc.utils.dice.ast; +/** + * A node that represents a variable reference + * + * @author ben + * + */ public class VariableDiceNode implements IDiceASTNode { + /** + * The variable referenced by this node + */ private String var; + /** + * Create a new node representing the specified variable + * + * @param data + * The name of the variable being referenced + */ public VariableDiceNode(String data) { this.var = data; } - @Override - public boolean isOperator() { - return false; - } - /** * Get the variable referenced by this AST node * @@ -20,7 +30,22 @@ public class VariableDiceNode implements IDiceASTNode { public String getVariable() { return var; } - + + /* + * (non-Javadoc) + * + * @see bjc.utils.dice.ast.IDiceASTNode#isOperator() + */ + @Override + public boolean isOperator() { + return false; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ @Override public String toString() { return var; |
