/* --------------------------------------------------------- * * __________ 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;} }