diff options
Diffstat (limited to 'dice-lang/src/main/java/bjc/dicelang/ast')
14 files changed, 811 insertions, 8 deletions
diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java new file mode 100644 index 0000000..93b56de --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTEvaluator.java @@ -0,0 +1,261 @@ +package bjc.dicelang.ast; + +import java.util.function.BinaryOperator; + +import bjc.dicelang.ComplexDice; + +import bjc.dicelang.ast.nodes.DiceASTType; +import bjc.dicelang.ast.nodes.DiceLiteralNode; +import bjc.dicelang.ast.nodes.DiceLiteralType; +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.ILiteralDiceNode; +import bjc.dicelang.ast.nodes.IntegerLiteralNode; +import bjc.dicelang.ast.nodes.OperatorDiceNode; +import bjc.dicelang.ast.nodes.VariableDiceNode; + +import bjc.utils.data.GenHolder; +import bjc.utils.data.IPair; +import bjc.utils.data.Pair; +import bjc.utils.funcdata.FunctionalMap; +import bjc.utils.funcdata.IFunctionalMap; +import bjc.utils.funcdata.bst.ITreePart.TreeLinearizationMethod; +import bjc.utils.parserutils.AST; + +/** + * Evaluate a dice AST to an integer value + * + * @author ben + * + */ +public class DiceASTEvaluator { + private static final class ArithmeticCollapser + implements IOperatorCollapser { + private OperatorDiceNode type; + + private BinaryOperator<Integer> valueOp; + + public ArithmeticCollapser(OperatorDiceNode type, + BinaryOperator<Integer> valueOp) { + this.type = type; + this.valueOp = valueOp; + } + + @Override + public IPair<Integer, AST<IDiceASTNode>> apply( + IPair<Integer, AST<IDiceASTNode>> leftNode, + IPair<Integer, AST<IDiceASTNode>> rightNode) { + return leftNode.merge((leftValue, leftAST) -> { + return rightNode.merge((rightValue, rightAST) -> { + if (type == OperatorDiceNode.DIVIDE + && rightValue == 0) { + throw new ArithmeticException( + "Attempted to divide by zero. The AST of the problem expression is " + + rightAST); + } + + return new Pair<>(valueOp.apply(leftValue, rightValue), + new AST<>(type, leftAST, rightAST)); + }); + }); + } + } + + /** + * Evaluate the provided AST to a numeric value + * + * @param expression + * The expression to evaluate + * @param enviroment + * The enviroment to look up variables in + * @return The integer value of the expression + */ + public static int evaluateAST(AST<IDiceASTNode> expression, + IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { + IFunctionalMap<IDiceASTNode, IOperatorCollapser> collapsers = + buildOperations(enviroment); + + return expression.collapse((node) -> { + return evaluateLeaf(node, enviroment); + }, collapsers::get, (pair) -> { + return pair.merge((left, right) -> left); + }); + } + + /** + * Build the map of operations to use when collapsing the AST + * + * @param enviroment + * The enviroment to evaluate bindings and such against + * @return The operations to use when collapsing the AST + */ + private static IFunctionalMap<IDiceASTNode, IOperatorCollapser> + buildOperations( + IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { + IFunctionalMap<IDiceASTNode, IOperatorCollapser> operatorCollapsers = + new FunctionalMap<>(); + + operatorCollapsers.put(OperatorDiceNode.ADD, + new ArithmeticCollapser(OperatorDiceNode.ADD, + (left, right) -> left + right)); + + operatorCollapsers.put(OperatorDiceNode.SUBTRACT, + new ArithmeticCollapser(OperatorDiceNode.SUBTRACT, + (left, right) -> left - right)); + + operatorCollapsers.put(OperatorDiceNode.MULTIPLY, + new ArithmeticCollapser(OperatorDiceNode.MULTIPLY, + (left, right) -> left * right)); + + operatorCollapsers.put(OperatorDiceNode.DIVIDE, + new ArithmeticCollapser(OperatorDiceNode.DIVIDE, + (left, right) -> left / right)); + + operatorCollapsers.put(OperatorDiceNode.ASSIGN, (left, right) -> { + return parseBinding(enviroment, left, right); + }); + + operatorCollapsers.put(OperatorDiceNode.COMPOUND, + DiceASTEvaluator::parseCompound); + + operatorCollapsers.put(OperatorDiceNode.GROUP, + DiceASTEvaluator::parseGroup); + + return operatorCollapsers; + } + + private static IPair<Integer, AST<IDiceASTNode>> parseBinding( + IFunctionalMap<String, AST<IDiceASTNode>> enviroment, + IPair<Integer, AST<IDiceASTNode>> left, + IPair<Integer, AST<IDiceASTNode>> right) { + return left.merge((leftValue, leftAST) -> { + return right.merge((rightValue, rightAST) -> { + String variableName = leftAST.applyToHead((node) -> { + if (node.getType() != DiceASTType.VARIABLE) { + throw new UnsupportedOperationException( + "Attempted to assign to '" + node + + "' which is not a variable"); + } + + return ((VariableDiceNode) node).getVariable(); + }); + + GenHolder<Boolean> selfReference = new GenHolder<>(false); + + DiceASTReferenceChecker refChecker = + new DiceASTReferenceChecker(selfReference, + variableName); + + rightAST.traverse(TreeLinearizationMethod.PREORDER, + refChecker); + + // Ignore meta-variable that'll be auto-frozen to restore + // definition sanity + if (selfReference.unwrap((bool) -> bool) + && !variableName.equals("last")) { + throw new UnsupportedOperationException( + "Variable '" + variableName + + "' references itself. Problematic definition: \n\t" + + rightAST); + } + + if (!variableName.equals("last")) { + enviroment.put(variableName, rightAST); + } else { + // Do nothing, last is a auto-handled meta-variable + } + + return new Pair<>(rightValue, new AST<>( + OperatorDiceNode.ASSIGN, leftAST, rightAST)); + }); + }); + } + + private static IPair<Integer, AST<IDiceASTNode>> parseCompound( + IPair<Integer, AST<IDiceASTNode>> leftNode, + IPair<Integer, AST<IDiceASTNode>> 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)); + }); + }); + } + + private static IPair<Integer, AST<IDiceASTNode>> parseGroup( + IPair<Integer, AST<IDiceASTNode>> leftNode, + IPair<Integer, AST<IDiceASTNode>> 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)); + }); + }); + } + + private static IPair<Integer, AST<IDiceASTNode>> evaluateLeaf( + IDiceASTNode leafNode, + IFunctionalMap<String, AST<IDiceASTNode>> enviroment) { + int returnedValue = 0; + + switch (leafNode.getType()) { + case LITERAL: + returnedValue = evaluateLiteral(leafNode, returnedValue); + + break; + case VARIABLE: + String variableName = + ((VariableDiceNode) leafNode).getVariable(); + + returnedValue = evaluateAST(enviroment.get(variableName), + enviroment); + break; + case OPERATOR: + throw new UnsupportedOperationException( + "Operator '" + leafNode + "' cannot be a leaf."); + default: + break; + + } + + return new Pair<>(returnedValue, new AST<>(leafNode)); + } + + private static int evaluateLiteral(IDiceASTNode leafNode, + int returnedValue) { + DiceLiteralType literalType = + ((ILiteralDiceNode) leafNode).getLiteralType(); + + switch (literalType) { + case DICE: + returnedValue = ((DiceLiteralNode) leafNode).getValue(); + break; + case INTEGER: + returnedValue = ((IntegerLiteralNode) leafNode).getValue(); + break; + default: + throw new UnsupportedOperationException("Literal value '" + + leafNode + "' is of a type (" + literalType + + ") not currently supported."); + } + return returnedValue; + } +} 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 db2ba98..f6500e3 100644 --- a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTParser.java @@ -2,10 +2,14 @@ package bjc.dicelang.ast; import java.util.InputMismatchException; -import bjc.dicelang.old.ast.nodes.IDiceASTNode; -import bjc.dicelang.old.ast.nodes.LiteralDiceNode; -import bjc.dicelang.old.ast.nodes.OperatorDiceNode; -import bjc.dicelang.old.ast.nodes.VariableDiceNode; +import bjc.dicelang.IDiceExpression; +import bjc.dicelang.ast.nodes.DiceLiteralNode; +import bjc.dicelang.ast.nodes.DiceLiteralType; +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.ILiteralDiceNode; +import bjc.dicelang.ast.nodes.IntegerLiteralNode; +import bjc.dicelang.ast.nodes.OperatorDiceNode; +import bjc.dicelang.ast.nodes.VariableDiceNode; import bjc.utils.funcdata.IFunctionalList; import bjc.utils.parserutils.AST; import bjc.utils.parserutils.TreeConstructor; @@ -26,8 +30,8 @@ public class DiceASTParser { */ public static AST<IDiceASTNode> createFromString( IFunctionalList<String> tokens) { - AST<String> rawTokens = - TreeConstructor.constructTree(tokens, (token) -> { + AST<String> rawTokens = TreeConstructor.constructTree(tokens, + (token) -> { return isOperatorNode(token); }, (operator) -> false, null); // The last argument is valid because there are no special @@ -48,8 +52,22 @@ public class DiceASTParser { } private static IDiceASTNode convertLeafNode(String leafNode) { - if (LiteralDiceNode.isLiteral(leafNode)) { - return new LiteralDiceNode(leafNode); + DiceLiteralType literalType = ILiteralDiceNode + .getLiteralType(leafNode); + + if (literalType != null) { + switch (literalType) { + case DICE: + return new DiceLiteralNode( + IDiceExpression.toExpression(leafNode)); + case INTEGER: + return new IntegerLiteralNode( + Integer.parseInt(leafNode)); + default: + throw new InputMismatchException( + "Cannot convert string '" + leafNode + + "' into a literal."); + } } return new VariableDiceNode(leafNode); diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java new file mode 100644 index 0000000..809243a --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/DiceASTReferenceChecker.java @@ -0,0 +1,60 @@ +package bjc.dicelang.ast; + +import java.util.function.Consumer; + +import bjc.dicelang.ast.nodes.DiceASTType; +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.dicelang.ast.nodes.VariableDiceNode; +import bjc.utils.data.IHolder; + +/** + * Check if the specified node references a particular variable + * + * @author ben + * + */ +public final class DiceASTReferenceChecker + implements Consumer<IDiceASTNode> { + /** + * This is true if the specified node references the set variable + */ + private IHolder<Boolean> referencesVariable; + + private String varName; + + /** + * Create a new reference checker + * + * @param referencesVar + * The holder of whether the variable is referenced or not + * @param varName + * The variable to check for references in + */ + public DiceASTReferenceChecker(IHolder<Boolean> referencesVar, + String varName) { + this.referencesVariable = referencesVar; + this.varName = varName; + } + + @Override + public void accept(IDiceASTNode astNode) { + referencesVariable.transform((bool) -> isDirectReference(astNode)); + } + + /** + * Check if a given AST node directly references the specified variable + * + * @param astNode + * The node to check + * @return Whether or not the node directly the variable + */ + private boolean isDirectReference(IDiceASTNode astNode) { + if (astNode.getType() == DiceASTType.VARIABLE) { + VariableDiceNode node = (VariableDiceNode) astNode; + + return node.getVariable().equals(varName); + } + + return false; + } +}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java new file mode 100644 index 0000000..ed818d4 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/IOperatorCollapser.java @@ -0,0 +1,18 @@ +package bjc.dicelang.ast; + +import java.util.function.BinaryOperator; + +import bjc.dicelang.ast.nodes.IDiceASTNode; +import bjc.utils.data.IPair; +import bjc.utils.parserutils.AST; + +/** + * Alias for operator collapsers. Because 68-char types are too long + * + * @author ben + * + */ +public interface IOperatorCollapser + extends BinaryOperator<IPair<Integer, AST<IDiceASTNode>>> { + // Just an alias +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java new file mode 100644 index 0000000..9feb461 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceASTType.java @@ -0,0 +1,27 @@ +package bjc.dicelang.ast.nodes; + +/** + * An enum to represent the type of node an AST node is + * + * @author ben + * + */ +public enum DiceASTType { + /** + * A node that contains a literal value + */ + LITERAL, + /** + * A node that contains an operator expression + */ + OPERATOR, + /** + * A node that contains a variable reference + */ + VARIABLE; + + @Override + public String toString() { + return this.name().toLowerCase(); + } +}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java new file mode 100644 index 0000000..82c764d --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralNode.java @@ -0,0 +1,57 @@ +package bjc.dicelang.ast.nodes; + +import bjc.dicelang.IDiceExpression; + +/** + * Represents a literal backed by a dice expression + * + * @author ben + * + */ +public class DiceLiteralNode implements ILiteralDiceNode { + private IDiceExpression expression; + + /** + * Create a new literal from an expression + * + * @param exp + * The expression to attempt to create a literal from + */ + public DiceLiteralNode(IDiceExpression exp) { + expression = exp; + } + + /** + * Check if this node can be optimized to a constant + * + * @return Whether or not this node can be optimized to a constant + * @see bjc.dicelang.IDiceExpression#canOptimize() + */ + public boolean canOptimize() { + return expression.canOptimize(); + } + + @Override + public DiceLiteralType getLiteralType() { + return DiceLiteralType.DICE; + } + + /** + * Return a value from the expression being represented + * + * @return A value from the expression being represented + */ + public int getValue() { + return expression.roll(); + } + + /** + * Optimize this node to a constant if possible + * + * @return This node in constant form if possible + * @see bjc.dicelang.IDiceExpression#optimize() + */ + public int optimize() { + return expression.optimize(); + } +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java new file mode 100644 index 0000000..41c6b05 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceLiteralType.java @@ -0,0 +1,18 @@ +package bjc.dicelang.ast.nodes; + +/** + * Represents the type of literals that can be in an AST + * + * @author ben + * + */ +public enum DiceLiteralType { + /** + * Represents a integral constant + */ + INTEGER, + /** + * Represents a dice literal + */ + DICE; +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java new file mode 100644 index 0000000..76aa2e3 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/DiceOperatorType.java @@ -0,0 +1,25 @@ +package bjc.dicelang.ast.nodes; + +/** + * Represents the different type of operators. + * + * Mostly, what distinguishes groups is that all the operators in a group + * have similiar precedence, and operate on similiar things + * + * @author ben + * + */ +public enum DiceOperatorType { + /** + * Represents operators that do math operations + */ + MATH, + /** + * Represents operators that do things with dice + */ + DICE, + /** + * Represents operators that do things with expressions + */ + EXPRESSION; +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java new file mode 100644 index 0000000..b7bf9a6 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IDiceASTNode.java @@ -0,0 +1,23 @@ +package bjc.dicelang.ast.nodes; + +/** + * The interface for a node in a dice AST + * + * @author ben + * + */ +public interface IDiceASTNode { + /** + * Get the type of AST node this node is + * + * @return The type of AST node this AST node is + */ + public DiceASTType getType(); + + /** + * Check if this node represents an operator or not + * + * @return Whether or not this node represents an operator + */ + public boolean isOperator(); +}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java new file mode 100644 index 0000000..b12b516 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/ILiteralDiceNode.java @@ -0,0 +1,54 @@ +package bjc.dicelang.ast.nodes; + +import org.apache.commons.lang3.StringUtils; + +/** + * Represents a literal of some type in the AST + * + * @author ben + * + */ +public interface ILiteralDiceNode extends IDiceASTNode { + @Override + default DiceASTType getType() { + return DiceASTType.LITERAL; + } + + @Override + default boolean isOperator() { + return false; + } + + /** + * Get the type of literal this node represents + * + * @return The type of literal this node represents + */ + DiceLiteralType getLiteralType(); + + /** + * Check if a token represents a literal, and if so, what type + * + * @param tok + * The token to check + * @return The type the literal would be if it is one, or null + * otherwise + */ + static DiceLiteralType getLiteralType(String tok) { + if (StringUtils.countMatches(tok, 'c') == 1 + && !tok.equalsIgnoreCase("c")) { + return DiceLiteralType.DICE; + } else if (StringUtils.countMatches(tok, 'd') == 1 + && !tok.equalsIgnoreCase("d")) { + return DiceLiteralType.DICE; + } else { + try { + Integer.parseInt(tok); + return DiceLiteralType.INTEGER; + } catch (@SuppressWarnings("unused") NumberFormatException nfex) { + // We don't care about details + return null; + } + } + } +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java new file mode 100644 index 0000000..415f30f --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/IntegerLiteralNode.java @@ -0,0 +1,35 @@ +package bjc.dicelang.ast.nodes; + +/** + * Represents an integer literal of some kind + * + * @author ben + * + */ +public class IntegerLiteralNode implements ILiteralDiceNode { + private int value; + + /** + * Create a new integer literal from the given number + * + * @param val + * The value this node represents + */ + public IntegerLiteralNode(int val) { + value = val; + } + + @Override + public DiceLiteralType getLiteralType() { + return DiceLiteralType.INTEGER; + } + + /** + * Get the value this node represents + * + * @return The integer value of this node + */ + public int getValue() { + return value; + } +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java new file mode 100644 index 0000000..d034943 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/OperatorDiceNode.java @@ -0,0 +1,100 @@ +package bjc.dicelang.ast.nodes; + +import static bjc.dicelang.ast.nodes.DiceOperatorType.*; + +// The following classes need to be changed upon addition of a new operator +// 1. DiceASTExpression +// 2. DiceASTFlattener +// 3. DiceASTParser +/** + * A node that represents an operator + * + * @author ben + * + */ +public enum OperatorDiceNode implements IDiceASTNode { + /** + * Represents adding two nodes + */ + ADD(MATH), + /** + * Represents assigning one node to another + */ + ASSIGN(EXPRESSION), + /** + * Representings combining two node values together + */ + COMPOUND(DICE), + /** + * Represents dividing two nodes + */ + DIVIDE(MATH), + /** + * Represents using one node a variable number of times + */ + GROUP(DICE), + /** + * Represents multiplying two nodes + */ + MULTIPLY(MATH), + /** + * Represents subtracting two nodes + */ + SUBTRACT(MATH); + + /** + * Represents the group of operator this operator is sorted into. + * + */ + public final DiceOperatorType type; + + private OperatorDiceNode(DiceOperatorType ty) { + type = ty; + } + + /** + * 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) { + case ":=": + return ASSIGN; + case "+": + return ADD; + case "-": + return SUBTRACT; + case "*": + return MULTIPLY; + case "/": + return DIVIDE; + case "d": + case "group": + return GROUP; + case "c": + case "compound": + return COMPOUND; + default: + throw new IllegalArgumentException( + s + " is not a valid operator node"); + } + } + + @Override + public DiceASTType getType() { + return DiceASTType.OPERATOR; + } + + /* + * (non-Javadoc) + * + * @see bjc.utils.dice.ast.IDiceASTNode#isOperator() + */ + @Override + public boolean isOperator() { + return true; + } +} diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java new file mode 100644 index 0000000..da66608 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/VariableDiceNode.java @@ -0,0 +1,101 @@ +package bjc.dicelang.ast.nodes; + +/** + * A node that represents a reference to a variable + * + * @author ben + * + */ +public class VariableDiceNode implements IDiceASTNode { + /** + * The variable referenced by this node + */ + private String variableName; + + /** + * Create a new node representing the specified variable + * + * @param varName + * The name of the variable being referenced + */ + public VariableDiceNode(String varName) { + this.variableName = varName; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + // Handle special cases + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (getClass() != obj.getClass()) { + return false; + } else { + VariableDiceNode other = (VariableDiceNode) obj; + + if (variableName == null) { + if (other.variableName != null) { + return false; + } + } else if (!variableName.equals(other.variableName)) { + return false; + } + + return true; + } + } + + @Override + public DiceASTType getType() { + return DiceASTType.VARIABLE; + } + + /** + * Get the variable referenced by this AST node + * + * @return the variable referenced by this AST node + */ + public String getVariable() { + return variableName; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((variableName == null) ? 0 : variableName.hashCode()); + return result; + } + + /* + * (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 variableName; + } +}
\ No newline at end of file diff --git a/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java new file mode 100644 index 0000000..cfa2511 --- /dev/null +++ b/dice-lang/src/main/java/bjc/dicelang/ast/nodes/package-info.java @@ -0,0 +1,6 @@ +/** + * Classes for nodes in the dice-lang AST + * @author ben + * + */ +package bjc.dicelang.ast.nodes;
\ No newline at end of file |
