public final class Verifier extends java.lang.Object implements ExpressionParserTokenTypes
AND, ASSIGN, BIT_AND, BIT_COMP, BIT_OR, BIT_XOR, BOOL_FALSE, BOOL_TRUE, CAST, COMMA, DEC_LITERAL, DIGIT, DIVIDE, DOT, DSTRING, EOF, EQUALS, GOTO, GT, GTE, HASH, HEX_LITERAL, HEXDIGIT, IDENTITY, IS_NULL, LETTER, LPARENS, LSHIFT, LT, LTE, METH_BOOLEAN, METH_DOUBLE, METH_INT, METH_LONG, METH_OBJ, MINUS, MODULO, MULTIPLY, NOT, NOT_EQ, NOT_NULL, NULL, NULL_TREE_LOOKAHEAD, NUM_LITERAL, OR, PLUS, POSPARM, RPARENS, RSHIFT, SSTRING, STRING, SYM_CHAR, SYMBOL, UN_MINUS, VALID_SYM_CHAR, WS, ZRSHIFT
Constructor and Description |
---|
Verifier() |
Modifier and Type | Method and Description |
---|---|
private static boolean |
isComparable(java.lang.Class cls)
Tests if the class implements the
Comparable interface. |
private static boolean |
isFloat(java.lang.Class cls)
Tests if the class represents one of the floating point types.
|
private static boolean |
isIntegral(java.lang.Class cls)
Tests if the class represents one of the integral types.
|
private static boolean |
isLogicalOperator(int type)
Tests whether the token type represents a logical operator.
|
private static boolean |
isNumeric(java.lang.Class cls)
Tests if the class represents one of the numeric types (either
integral or floating point).
|
static java.lang.Class |
resolveDataType(ExtraAst ast)
Walks the tree and determines the data type of the expression's result.
|
static java.lang.Class |
widestNumericType(java.lang.Class op1,
java.lang.Class op2)
Returns the widest representation of either of the two numeric operands
and will return a floating point value in preference to an integral
value if either of the operands are floating point.
|
public static java.lang.Class resolveDataType(ExtraAst ast) throws java.lang.IllegalArgumentException, java.lang.UnsupportedOperationException
The operator tests that are implemented:
Operator Operand 1 Type Operand 2 Type Return Type ------------- ----------------- ----------------- -------------- NOT Boolean n/a Boolean AND Boolean Boolean Boolean OR Boolean Boolean Boolean GT same as op2 same as op1 Boolean LT same as op2 same as op1 Boolean GTE same as op2 same as op1 Boolean LTE same as op2 same as op1 Boolean EQUALS same as op2 same as op1 Boolean NOT_EQ same as op2 same as op1 Boolean RSHIFT Integral Integral same as op1 LSHIFT Integral Integral same as op1 ZRSHIFT Integral Integral same as op1 BIT_AND Integral Integral same as op1 BIT_OR Integral Integral same as op1 BIT_XOR Integral Integral same as op1 BIT_COMP Integral Integral same as op1 LPARENS n/a n/a n/a IS_NULL n/a n/a Boolean NOT_NULL n/a n/a Boolean UN_MINUS Numeric n/a same as op1 MULTIPLY Numeric Numeric widened Numeric DIVIDE Numeric Numeric widened Numeric MODULO Numeric Numeric widened Numeric PLUS Numeric Numeric widened Numeric MINUS Numeric Numeric widened Numeric CAST any n/a user-specified classThe entries specified as 'same as op1' or 'same as op2' indicate that operands must meet one of the following conditions:
Comparable
interface
Numeric types refer to the following: Double, Long, Float, Integer, Character, Short and Byte.
Integral types are Long, Integer, Character, Short and Byte.
LPARENS
doesn't exist in the final tree (and even if it
did it would just return the data type of its contained expression).
For this reason, no LPARENS
processing is implemented.
IS_NULL
and NOT_NULL
are artificial
operators created by the parser whenever an equality or inequality
test against the null
literal is encountered. For this
reason, no verification is done since the result is always a
Boolean and the type of the operand is always some valid class.
The arithmetic operators do force a widening conversion on the output
type that is based on the types of the input. Please see
widestNumericType(java.lang.Class, java.lang.Class)
for more details.
The binary logical comparison operators will have the common operand
data type cached in the operator node via the method
ExtraAst.setOperandType(java.lang.Class)
. This will be done for GT, LT, GTE,
LTE, EQUALS and NOT_EQ. The resulting common operand type will be
set to the wider of operand1 or operand2. The resulting
Class
instance will be stored in the AST.
The following literal processing occurs:
Literal Type Class ----------------- ---------------------- NUM_LITERAL java.lang.Long.TYPE or java.lang.Integer.TYPE HEX_LITERAL java.lang.Long.TYPE or java.lang.Integer.TYPE DEC_LITERAL java.lang.Double.TYPE STRING java.lang.String.class BOOL_TRUE java.lang.Boolean.TYPE BOOL_FALSE java.lang.Boolean.TYPE NULL nullThe following method call processing occurs:
Method Call Class ----------------- ---------------------- METH_BOOLEAN java.lang.Boolean (.TYPE or .class) METH_DOUBLE java.lang.Double (.TYPE or .class) METH_LONG java.lang.Long (.TYPE or .class) METH_INT java.lang.Integer (.TYPE or .class) METH_OBJ return type from the embedded FunctionAny method object that exists in the tree has already been resolved to a
Function
object that represents all necessary
information about the method including its return type. This is used
as the return value for METH_OBJ
nodes.
At the end of all processing, if an exception is not thrown and if the
ExtraAst.getExtra()
property is null
, the node's
class (data type) will be cached using ExtraAst.setExtra(java.lang.Object)
.
ast
- The root AST node of an expression tree (or sub-tree).java.lang.IllegalArgumentException
- If the AST argument is null
.java.lang.UnsupportedOperationException
- On any verification error.public static java.lang.Class widestNumericType(java.lang.Class op1, java.lang.Class op2)
long
and one is a
float
. In this case, the widest safe representation
is a double
. All other cases will always return a
type that is the same as one or the other operand.
The following precedence order is followed:
java.lang.Double, 64-bits java.lang.Long, 64-bits java.lang.Float, 32-bits java.lang.Integer, 32-bits java.lang.Short, 16-bits java.lang.Character, 16-bits java.lang.Byte 8-bits
op1
- The first operand class.op2
- The second operand class.null
if neither
class is numeric.private static boolean isLogicalOperator(int type)
type
- Token type to be tested.true
if the token type represents a logical
operator, else false
.private static boolean isComparable(java.lang.Class cls)
Comparable
interface.cls
- The class to test.true
if the class implements the
Comparable
interface.private static boolean isIntegral(java.lang.Class cls)
cls
- The class to test.true
if the class is an integral type.private static boolean isFloat(java.lang.Class cls)
cls
- The class to test.true
if the class is an floating point type.private static boolean isNumeric(java.lang.Class cls)
cls
- The class to test.true
if the class is a numeric type.