summaryrefslogtreecommitdiff
path: root/dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2016-04-08 13:29:48 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2016-04-08 13:29:48 -0400
commit90d1cc6c9f47f1b6f74fb57e07865795a46c23b8 (patch)
treeb74cd5b9989c9f5a1bbde1e1b8c751faf9cb7086 /dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java
parentb1df3ff8c890bf6d4cc16fb4f28ddb7833512d71 (diff)
Change to data interfaces, as well as prepare to rewrite parser
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java')
-rw-r--r--dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java145
1 files changed, 145 insertions, 0 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java b/dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java
new file mode 100644
index 0000000..a7500a8
--- /dev/null
+++ b/dice-lang/src/main/java/bjc/dicelang/old/ast/DiceASTFlattener.java
@@ -0,0 +1,145 @@
+package bjc.dicelang.old.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.OperatorDiceExpression;
+import bjc.dicelang.DiceExpressionType;
+import bjc.dicelang.IDiceExpression;
+import bjc.dicelang.ReferenceDiceExpression;
+import bjc.dicelang.ScalarDie;
+import bjc.dicelang.ast.nodes.DiceASTType;
+import bjc.dicelang.ast.nodes.IDiceASTNode;
+import bjc.dicelang.ast.nodes.LiteralDiceNode;
+import bjc.dicelang.ast.nodes.OperatorDiceNode;
+import bjc.dicelang.ast.nodes.VariableDiceNode;
+import bjc.utils.parserutils.AST;
+
+/**
+ * Flatten an {@link AST} of {@link IDiceASTNode} into a
+ * {@link IDiceExpression}
+ *
+ * @author ben
+ *
+ */
+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
+ *
+ * @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 OperatorDiceExpression(right, left,
+ DiceExpressionType.ADD);
+ });
+ opCollapsers.put(OperatorDiceNode.SUBTRACT, (left, right) -> {
+ return new OperatorDiceExpression(right, left,
+ DiceExpressionType.SUBTRACT);
+ });
+ opCollapsers.put(OperatorDiceNode.MULTIPLY, (left, right) -> {
+ return new OperatorDiceExpression(right, left,
+ DiceExpressionType.MULTIPLY);
+ });
+ opCollapsers.put(OperatorDiceNode.DIVIDE, (left, right) -> {
+ return new OperatorDiceExpression(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;
+ }
+
+ /**
+ * 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(new NodeCollapser(env), opCollapsers::get,
+ (r) -> r);
+ }
+}