diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-03-21 21:42:27 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-03-21 21:42:27 -0400 |
| commit | 523eea5fdbecaea141f3aafe89b307f1e9e75b25 (patch) | |
| tree | 360112827177793cb6fc89ba1bc1d2f689359c22 /BJC-Utils2/src/main/java/bjc | |
| parent | 6d1c64021b9887f943b24732adae364d16bb0eb3 (diff) | |
Polished up work on AST-based dice
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc')
6 files changed, 207 insertions, 2 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 new file mode 100644 index 0000000..3b81888 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTExpression.java @@ -0,0 +1,144 @@ +package bjc.utils.dice.ast; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BinaryOperator; + +import org.apache.commons.lang3.StringUtils; + +import bjc.utils.data.Pair; +import bjc.utils.dice.ComplexDice; +import bjc.utils.dice.CompoundDice; +import bjc.utils.dice.IDiceExpression; +import bjc.utils.parserutils.AST; + +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)); + } + } + } + + private static + Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> + buildOperations(Map<String, DiceASTExpression> env) { + Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> opCollapsers = + new HashMap<>(); + + opCollapsers.put(OperatorDiceNode.ADD, (left, right) -> { + return left.merge((lval, last) -> right.merge((rval, rast) -> { + return new Pair<>(lval + rval, + new AST<>(OperatorDiceNode.ADD, last, rast)); + })); + + }); + opCollapsers.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)); + })); + + }); + opCollapsers.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)); + })); + + }); + opCollapsers.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)); + })); + }); + + opCollapsers.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); + + env.put(nam, new DiceASTExpression(rast, env)); + + return new Pair<>(rval, + new AST<>(OperatorDiceNode.ASSIGN, last, rast)); + })); + }); + + opCollapsers.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)); + })); + }); + opCollapsers.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)); + })); + }); + + return opCollapsers; + } + + @Override + public int roll() { + Map<IDiceASTNode, BinaryOperator<Pair<Integer, AST<IDiceASTNode>>>> operations = + buildOperations(env); + + return ast.collapse(this::evalLeaf, operations::get, + (r) -> r.merge((left, right) -> left)); + } + + @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 3cf1d4e..da402c3 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 @@ -29,7 +29,7 @@ public class DiceASTFlattener { return new ReferenceDiceExpression( ((VariableDiceNode) nod).getVariable(), env); } - } , opCollapsers, (r) -> r); + } , opCollapsers::get, (r) -> r); } private static Map<IDiceASTNode, BinaryOperator<IDiceExpression>> buildOperations( 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 new file mode 100644 index 0000000..04cc99b --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFreezer.java @@ -0,0 +1,47 @@ +package bjc.utils.dice.ast; + +import java.util.Map; + +import bjc.utils.parserutils.AST; + +public class DiceASTFreezer { + public static AST<IDiceASTNode> freezeAST(AST<IDiceASTNode> tree, + Map<String, AST<IDiceASTNode>> env) { + return tree.collapse((nod) -> { + if (nod instanceof VariableDiceNode) { + return expandNode((VariableDiceNode) nod, env); + } else { + // Type is specified here so compiler can know the type + // we're using + return new AST<IDiceASTNode>(nod); + } + } , (op) -> (left, right) -> { + return new AST<IDiceASTNode>(op, left, right); + } , (r) -> r); + } + + public static AST<IDiceASTNode> freezeAST(DiceASTExpression tree, + Map<String, DiceASTExpression> env) { + return tree.getAst().collapse((nod) -> { + if (nod instanceof VariableDiceNode) { + return expandNode2((VariableDiceNode) nod, env); + } else { + // Type is specified here so compiler can know the type + // we're using + return new AST<IDiceASTNode>(nod); + } + } , (op) -> (left, right) -> { + 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/LiteralDiceNode.java b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java index 5bfbc85..20358fb 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 @@ -20,4 +20,9 @@ public class LiteralDiceNode implements IDiceASTNode { public String getData() { return data; } + + @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 84f45aa..92b49b7 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 @@ -1,8 +1,12 @@ package bjc.utils.dice.ast; +// The following classes need to be changed upon addition of a new operator +// 1. DiceASTExpression +// 2. DiceASTFlattener +// 3. DiceASTParser public enum OperatorDiceNode implements IDiceASTNode { ASSIGN, ADD, SUBTRACT, MULTIPLY, DIVIDE, GROUP, COMPOUND; - + @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 1d3a63c..6ae3189 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 @@ -20,4 +20,9 @@ public class VariableDiceNode implements IDiceASTNode { public String getVariable() { return var; } + + @Override + public String toString() { + return var; + } } |
