diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-03-21 17:57:12 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2016-03-21 17:57:12 -0400 |
| commit | 7549e7d1b671738d9ebe9a6bf12b666b2bcb5b42 (patch) | |
| tree | 3a5cbd29fe7dde13bffeebbfd6943d1065614093 /BJC-Utils2/src/main/java/bjc/utils | |
| parent | 1bff7e49ed64d74e36d901e84c594cf63b58350b (diff) | |
Built AST representation of Dice things
Diffstat (limited to 'BJC-Utils2/src/main/java/bjc/utils')
6 files changed, 243 insertions, 0 deletions
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 new file mode 100644 index 0000000..3cf1d4e --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTFlattener.java @@ -0,0 +1,83 @@ +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.dice.BindingDiceExpression; +import bjc.utils.dice.ComplexDice; +import bjc.utils.dice.CompoundDice; +import bjc.utils.dice.CompoundDiceExpression; +import bjc.utils.dice.DiceExpressionType; +import bjc.utils.dice.IDiceExpression; +import bjc.utils.dice.ReferenceDiceExpression; +import bjc.utils.dice.ScalarDie; +import bjc.utils.parserutils.AST; + +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, (r) -> r); + } + + 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); + }); + opCollapsers.put(OperatorDiceNode.SUBTRACT, (left, right) -> { + return new CompoundDiceExpression(right, left, + DiceExpressionType.SUBTRACT); + }); + opCollapsers.put(OperatorDiceNode.MULTIPLY, (left, right) -> { + return new CompoundDiceExpression(right, left, + DiceExpressionType.MULTIPLY); + }); + opCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> { + return new CompoundDiceExpression(right, left, + DiceExpressionType.DIVIDE); + }); + opCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> { + return new BindingDiceExpression(left, right, env); + }); + opCollapsers.put(OperatorDiceNode.COMPOUND, (left, right) -> { + return new CompoundDice(left, right); + }); + opCollapsers.put(OperatorDiceNode.GROUP, (left, right) -> { + return new ComplexDice(left, right); + }); + + return opCollapsers; + } + + 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)); + } + } +} 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 new file mode 100644 index 0000000..d56ad0e --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/DiceASTParser.java @@ -0,0 +1,78 @@ +package bjc.utils.dice.ast; + +import org.apache.commons.lang3.StringUtils; + +import bjc.utils.funcdata.FunctionalList; +import bjc.utils.funcdata.FunctionalStringTokenizer; +import bjc.utils.parserutils.AST; +import bjc.utils.parserutils.ShuntingYard; +import bjc.utils.parserutils.TreeConstructor; + +public class DiceASTParser { + private static ShuntingYard<String> yard; + + static { + yard = new ShuntingYard<>(); + + 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 + } + + public AST<IDiceASTNode> buildAST(String exp) { + 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<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); + } + }); + + 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) { + 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; + } + } + } +} 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 new file mode 100644 index 0000000..3fb14fe --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/IDiceASTNode.java @@ -0,0 +1,5 @@ +package bjc.utils.dice.ast; + +public interface IDiceASTNode { + 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 new file mode 100644 index 0000000..5bfbc85 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/LiteralDiceNode.java @@ -0,0 +1,23 @@ +package bjc.utils.dice.ast; + +public class LiteralDiceNode implements IDiceASTNode { + private String data; + + public LiteralDiceNode(String data) { + this.data = data; + } + + @Override + public boolean isOperator() { + return false; + } + + /** + * Get the data stored in this AST node + * + * @return the data stored in this AST node + */ + public String getData() { + 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 new file mode 100644 index 0000000..84f45aa --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/OperatorDiceNode.java @@ -0,0 +1,31 @@ +package bjc.utils.dice.ast; + +public enum OperatorDiceNode implements IDiceASTNode { + ASSIGN, ADD, SUBTRACT, MULTIPLY, DIVIDE, GROUP, COMPOUND; + + @Override + public boolean isOperator() { + return true; + } + + public static OperatorDiceNode fromString(String s) { + switch(s) { + case ":=": + return ASSIGN; + case "+": + return ADD; + case "-": + return SUBTRACT; + case "*": + return MULTIPLY; + case "/": + return DIVIDE; + case "d": + return GROUP; + case "c": + return COMPOUND; + default: + throw new IllegalArgumentException(s + " is not a valid operator node"); + } + } +} 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 new file mode 100644 index 0000000..1d3a63c --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/dice/ast/VariableDiceNode.java @@ -0,0 +1,23 @@ +package bjc.utils.dice.ast; + +public class VariableDiceNode implements IDiceASTNode { + private String var; + + public VariableDiceNode(String data) { + this.var = data; + } + + @Override + public boolean isOperator() { + return false; + } + + /** + * Get the variable referenced by this AST node + * + * @return the variable referenced by this AST node + */ + public String getVariable() { + return var; + } +} |
