/* --------------------------------------------------------- *
* __________ D E L T A S C R I P T *
* (_________() *
* / === / - A fast, dynamic scripting language *
* | == | - Version 4.13.11.0 *
* / === / - Developed by Adam R. Nelson *
* | = = | - 2011-2013 *
* / === / - Distributed under GNU LGPL v3 *
* (________() - http://github.com/ar-nelson/deltascript *
* *
* --------------------------------------------------------- */
package com.sector91.delta.script;
import static com.sector91.delta.script.parser.DScriptParser.LEFT_ASSOC;
import static com.sector91.delta.script.parser.DScriptParser.POSTFIX;
import static com.sector91.delta.script.parser.DScriptParser.PREFIX;
import static com.sector91.delta.script.parser.DScriptParser.RIGHT_ASSOC;
import static com.sector91.delta.script.parser.DScriptParser.STACKABLE;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
/**
* <p>Represents DeltaScript language operators. An operator object describes
* the symbols that make up the operator, the associativity and precedence of
* the operator, and whether the operator is unary or binary.</p>
*
* @author Adam R. Nelson
* @version 4.13.11.0
* @since 1.11.12.0
*/
public enum Operator
{
// OP (op, precedence, associativity, unary?, assign?)
/** Assigns a value to a variable in the current scope, overwriting values
* with the same name in the parent scope if no value with the same name
* exists in the current scope. The behavior changes if prefixed with the
* {@code def} keyword. */
ASSIGN ("=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #ADD} on a variable and then sets it.
* */
ADD_ASSIGN ("+=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #SUBTRACT} on a variable and then
* sets it. */
SUB_ASSIGN ("-=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #MULTIPLY} on a variable and then
* sets it. */
MUL_ASSIGN ("*=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #DIVIDE} on a variable and then sets
* it. */
DIV_ASSIGN ("/=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #MODULUS} on a variable and then sets
* it. */
MOD_ASSIGN ("%=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #EXPONENT} on a variable and then
* sets it. */
EXP_ASSIGN ("^=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #BIT_OR} on a variable and then sets
* it. */
OR_ASSIGN ("|=", 0, RIGHT_ASSOC, false, true),
/** Compound operator; performs {@link #BIT_AND} on a variable and then sets
* it. */
AND_ASSIGN ("&=", 0, RIGHT_ASSOC, false, true),
/** Boolean OR operation. Can also be used as a short-circuit operator;
* will only evaluate the right side if the left side is false. */
OR ("or", 5, LEFT_ASSOC, false, false),
/** Boolean AND operation. Can also be used as a short-circuit operator;
* will only evaluate the right side if the left side is true. */
AND ("and", 7, LEFT_ASSOC, false, false),
/** Test if the collection on the right contains the item on the left.
* Unlike other binary operators, it calls
* {@link DS_Object#operator(Operator, DS_Object)} on the right-hand
* argument, not the left. */
IN ("in", 9, LEFT_ASSOC, false, false),
/** Tests the equality of two objects using
* {@link DS_Object#equals(DS_Object)}. */
EQUAL ("==", 10, LEFT_ASSOC, false, false),
/** The inverse of {@link #EQUAL}. */
NOT_EQUAL ("!=", 10, LEFT_ASSOC, false, false),
/** Tests if the result of {@link DS_Object#compareTo(DS_Object)} from the
* left side to the right is less than 0. */
LESS_THAN ("<", 15, LEFT_ASSOC, false, false),
/** Tests if the result of {@link DS_Object#compareTo(DS_Object)} from the
* left side to the right is less than or equal to 0. */
LESS_OR_EQ ("<=", 15, LEFT_ASSOC, false, false),
/** Tests if the result of {@link DS_Object#compareTo(DS_Object)} from the
* left side to the right is greater than 0. */
GREATER_THAN (">", 15, LEFT_ASSOC, false, false),
/** Tests if the result of {@link DS_Object#compareTo(DS_Object)} from the
* left side to the right is greater than or equal to 0. */
GREATER_OR_EQ (">=", 15, LEFT_ASSOC, false, false),
/** Tests the "identity" of an object by using the {@link
* DS_Object#is(DS_Object)} method. Similar to Java's {@code instanceof}
* operator. */
INSTANCEOF ("is", 17, LEFT_ASSOC, false, false),
/** The inverse of {@link #INSTANCEOF}. */
NOT_INSTANCEOF("isnt", 17, LEFT_ASSOC, false, false),
/** Used to define the step of a range (e.g., {@code 1 to 5 by 2}), or to
* define a box (e.g., {@code 2 by 4}).*/
RANGE_STEP ("by", 18, LEFT_ASSOC, false, false),
/** When used on two {@link DS_Scalar}s, defines an <em>inclusive</em>
* range. */
RANGE_INC ("through",19, LEFT_ASSOC, false, false),
/** When used on two {@link DS_Scalar}s, defines an <em>exclusive</em>
* range; when used on two {@link DS_Vector}s, defines a line. */
RANGE_EXC ("to", 19, LEFT_ASSOC, false, false),
/** Performs mathematical addition, set/geometric union, or sequence/string
* concatenation. */
ADD ("+", 20, LEFT_ASSOC, false, false),
/** Performs mathematical subtraction, or a difference of sets, sequences,
* or shapes. */
SUBTRACT ("-", 20, LEFT_ASSOC, false, false),
/** Used for bitwise 'or' and for union of sets, shapes, etc. */
BIT_OR ("|", 21, LEFT_ASSOC, false, false),
/** Used for bitwise 'and' and for intersection of sets, shapes, etc. */
BIT_AND ("&", 22, LEFT_ASSOC, false, false),
/** Performs mathematical multiplication, or sequence/string duplication
* (e.g., {@code "abc" * 3 == "abcabcabc"}). */
MULTIPLY ("*", 25, LEFT_ASSOC, false, false),
/** Performs mathematical division. */
DIVIDE ("/", 25, LEFT_ASSOC, false, false),
/** Calculates the remainder of an integer division operation. */
MODULUS ("%", 25, LEFT_ASSOC, false, false),
/** Performs mathematical exponentiation; the same as using
* {@link Math#pow(double, double)}. */
EXPONENT ("^", 25, RIGHT_ASSOC, false, false),
/** Performs a cross product of two 3D vectors, using
* {@link DS_Vector#cross(DS_Vector)}. */
CROSS ("X", 25, LEFT_ASSOC, false, false),
/** Used to access members of objects or scopes. This is a special
* operator and does not behave like other binary operators; unary
* operators will be expanded around dot chains. */
DOT (".", 91, LEFT_ASSOC, false, false),
/** Represents the parenthesized argument list used to call a
* {@link DS_Callable}. Will throw an error if the target is not callable.
* This is a special operator and does not behave like other operators;
* unary operators will be expanded around calls. */
CALL ("(", 91, LEFT_ASSOC, false, false),
/** Represents the bracketed indexing operator used to access members of a
* {@link DS_Indexable}. Will throw an error if the target is not
* indexable or if the index is invalid or out of bounds. This is a
* special operator and does not behave like other operators; unary
* operators will be expanded around indexes. */
INDEX ("[", 91, LEFT_ASSOC, false, false),
/** Flips the sign of a {@link DS_Scalar} or {@link DS_Vector}. Should be
* functionally identical to using {@link #MULTIPLY} with <code>-1</code>
* on the right side. */
UNARY_MINUS ("-", -1, PREFIX, true, false),
/** Returns the opposite of an object's boolean value, as determined by
* {@link DS_Object#booleanValue()}. The result of this operator is always
* a {@link DS_Boolean}. */
NOT ("!", -1, PREFIX|STACKABLE, true, false),
/** Calculates a random value based on the object this operator is applied
* to. The way this random value is calculated depends on the type of the
* object: For numbers, it is a random number from 0 to the given number;
* for collections and strings, it is a random member of the collection;
* and for shapes, it is a random point inside the shape. */
RANDOM ("?", -1, PREFIX|STACKABLE, true, false),
/** Calculates the absolute value of a number, the magnitude of a vector,
* or the size of a collection. */
ABSOLUTE ("@", -1, PREFIX|STACKABLE, true, false),
/** Compound operator that adds 1 to a numeric variable and then sets the
* variable. Can only be used on variables, not constants. */
INCREMENT ("++", -1, POSTFIX, true, true),
/** Compound operator that subtracts 1 from a numeric variable and then
* sets the variable. Can only be used on variables, not constants. */
DECREMENT ("--", -1, POSTFIX, true, true);
public static final Operator[] BINARY_OPS, UNARY_OPS;
private static final Map<String, Operator> binaryOpsByStr,
unaryOpsByStr;
static {
List<Operator> binary = new ArrayList<Operator>();
List<Operator> unary = new ArrayList<Operator>();
binaryOpsByStr = new HashMap<String, Operator>();
unaryOpsByStr = new HashMap<String, Operator>();
for (Operator op : Operator.values())
{
if (op.isUnary)
{
unary.add(op);
unaryOpsByStr.put(op.str, op);
}
else
{
binary.add(op);
binaryOpsByStr.put(op.str, op);
}
}
BINARY_OPS = binary.toArray(new Operator[binary.size()]);
UNARY_OPS = unary.toArray(new Operator[unary.size()]);
}
public static Operator getBinaryOperator(String opStr)
{return binaryOpsByStr.get(opStr);}
public static Operator getUnaryOperator(String opStr)
{return unaryOpsByStr.get(opStr);}
public static boolean isBinaryOperator(String opStr)
{return binaryOpsByStr.containsKey(opStr);}
public static boolean isUnaryOperator(String opStr)
{return unaryOpsByStr.containsKey(opStr);}
public final String str;
public final int precedence, associativity;
public final boolean isUnary, isAssignment;
private Operator(String op, int precedence, int associativity,
boolean unary, boolean assignment)
{
this.str = op;
this.precedence = precedence;
this.associativity = associativity;
this.isUnary = unary;
this.isAssignment = assignment;
}
@Override public String toString()
{return str;}
}