blob: d0bcb7e50ca013089c07f90875b090a2a3f6a51d [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.taobao.weex.el.parse;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
/**
* Created by furture on 2017/8/28.
*/
public class Operators {
public static Object dot(Token left, Token right, Object context){
if(left == null || right == null){
return null;
}
Object leftValue = left.execute(context);
if(leftValue == null){
return null;
}
Object value = null;
if(right.getType() != Token.TYPE_IDENTIFIER){
Object identifter = right.execute(context);
if(identifter instanceof Double){
identifter = ((Double) identifter).intValue();
}
String key = identifter == null ? "" : identifter.toString().trim();
value = Operators.el(leftValue, key);
}else{
value = right.execute(leftValue);
}
if(value != null){
return value;
}
return specialKey(leftValue, right.getToken());
}
/**
* get key's value on object
* */
public static Object el(Object context, String key){
if(context == null){
return null;
}
// TODO
// if(context instanceof CellRenderContext){
// if(WXEnvironment.isApkDebugable()){
// throw new IllegalArgumentException("rong context CellRenderContext, you should pass it's stack");
// }
// context = ((CellRenderContext) context).stack;
// }
if(context instanceof ArrayStack){
ArrayStack stack = (ArrayStack) context;
for(int index=stack.size()-1; index >= 0; index--){
Object value = stack.get(index);
if(value instanceof Map){
Map map = (Map) value;
if(map.containsKey(key)){
return map.get(key);
}
}
}
}
if(context instanceof Stack){
Stack stack = (Stack) context;
for(int index=stack.size()-1; index >= 0; index--){
Object value = stack.get(index);
if(value instanceof Map){
Map map = (Map) value;
if(map.containsKey(key)){
return map.get(key);
}
}
}
}
if(context instanceof Map){
return ((Map) context).get(key);
}
if(context instanceof List){
List list = (List) context;
try{
return list.get(Integer.parseInt(key));
}catch (Exception e){}
}
if(context.getClass().isArray()){
try{
return Array.get(context, Integer.parseInt(key));
}catch (Exception e){}
}
return null;
}
public static Object specialKey(Object leftValue, String key){
if("length".equals(key)){
if(leftValue instanceof CharSequence){
return ((CharSequence) leftValue).length();
}
if(leftValue instanceof Map){
return ((Map) leftValue).size();
}
if(leftValue instanceof Map){
return ((Map) leftValue).size();
}
if(leftValue instanceof List){
return ((List) leftValue).size();
}
if(leftValue.getClass().isArray()){
return Array.getLength(leftValue);
}
}
return null;
}
public static Object plus(Token left, Token right, Object context){
Object leftValue = null;
Object rightValue = null;
if(left != null){
leftValue = left.execute(context);
}
if(right != null){
rightValue = right.execute(context);
}
if(leftValue instanceof CharSequence || rightValue instanceof CharSequence){
if(leftValue == null){
return rightValue;
}
return leftValue.toString() + (rightValue == null ? "" : rightValue.toString());
}
if(leftValue instanceof Number || rightValue instanceof Number){
return getNumber(leftValue) + getNumber(rightValue);
}
if(leftValue == null && rightValue == null){
return null;
}
if(leftValue == null){
return rightValue.toString();
}
return leftValue.toString() + (rightValue == null ? "" : rightValue.toString());
}
public static Object sub(Token left, Token right, Object context){
Object leftValue = null;
Object rightValue = null;
if(left != null){
leftValue = left.execute(context);
}
if(right != null){
rightValue = right.execute(context);
}
return getNumber(leftValue) - getNumber(rightValue);
}
public static Object div(Token left, Token right, Object context){
Object leftValue = null;
Object rightValue = null;
if(left != null){
leftValue = left.execute(context);
}
if(right != null){
rightValue = right.execute(context);
}
return getNumber(leftValue)/getNumber(rightValue);
}
public static Object mul(Token left, Token right, Object context){
Object leftValue = null;
Object rightValue = null;
if(left != null){
leftValue = left.execute(context);
}
if(right != null){
rightValue = right.execute(context);
}
return getNumber(leftValue)*getNumber(rightValue);
}
public static Object mod(Token left, Token right, Object context){
Object leftValue = null;
Object rightValue = null;
if(left != null){
leftValue = left.execute(context);
}
if(right != null){
rightValue = right.execute(context);
}
return (getNumber(leftValue))%(getNumber(rightValue));
}
/**
* condition expression
* */
public static Object condition(Token selfs, Token first, Token second, Object context){
boolean value = false;
if(selfs != null){
value = isTrue(selfs.execute(context));
}
if(value){
if(first != null){
return first.execute(context);
}
}else{
if(second != null){
return second.execute(context);
}
}
return null;
}
/**
* is token value is true
* */
public static boolean tokenTrue(Token selfs, Object context) {
if(selfs == null){
return false;
}
Object value = selfs.execute(context);
return isTrue(value);
}
/**
* get token number
* */
public static double tokenNumber(Token self, Object context) {
if(self == null){
return 0;
}
Object value = self.execute(context);
return getNumber(value);
}
/**
* isEquls operation
* */
public static boolean isEquals(Token left, Token right, Object context){
if(left == null && right == null){
return true;
}
Object leftValue = null;
if(left != null){
leftValue = left.execute(context);
}
Object rightValue = null;
if(right != null) {
rightValue = right.execute(context);
}
if(leftValue == null){
if(rightValue == null){
return true;
}
if(rightValue instanceof CharSequence){
if(isEmpty(rightValue.toString())){
return true;
}
}
return false;
}
if(rightValue == null){
if(isEmpty(leftValue.toString())){
return true;
}
return false;
}
if(leftValue instanceof Number){
if(rightValue instanceof Number){
return ((Number) leftValue).doubleValue() == ((Number) rightValue).doubleValue();
}
return ((Number) leftValue).doubleValue() == getNumber(rightValue);
}
if(rightValue instanceof Number){
return getNumber(leftValue) == ((Number) rightValue).doubleValue();
}
if(leftValue instanceof CharSequence
|| rightValue instanceof CharSequence){
return leftValue.toString().trim().equals(rightValue.toString().trim());
}
return leftValue.equals(rightValue);
}
/**
* check whether value is true
* */
public static boolean isTrue(Object value){
if(value == null){
return false;
}
if(value instanceof Number){
return ((Number) value).doubleValue() != 0;
}
String bool = value.toString().trim();
if("false".equals(bool)
|| "undefined".equals(bool)
|| "null".equals(bool)){
return false;
}
if(isEmpty(bool)){
return false;
}
return true;
}
/**
* check String value is empty
* */
public static boolean isEmpty(String value){
if (value == null){
return true;
}
for(int i=0; i<value.length(); i++){
if(value.charAt(i) != ' '){
return false;
}
}
return true;
}
/**
* get number
* */
public static double getNumber(Object value){
if(value == null){
return 0;
}
if(value instanceof Number){
return ((Number) value).doubleValue();
}
try{
return Double.parseDouble(value.toString());
}catch (Exception e){return 0;}
}
public static boolean isOpEnd(String op){
return isOpEnd(op.charAt(0));
}
/**
* op end, has none operation, should not enter operator stack.
* */
public static boolean isOpEnd(char op){
if(op == BRACKET_END
|| op == ARRAY_END
|| op == SPACE
|| op == ARRAY_SEPRATOR){
return true;
}
return false;
}
/**
* is not
* */
public static boolean isDot(String opStr){
char op = opStr.charAt(0);
return op == DOT || op == ARRAY_START;
}
public static final char BRACKET_END = ')';
public static final String BRACKET_END_STR = ")";
public static final char BRACKET_START = '(';
public static final String BRACKET_START_STR = "(";
public static final char QUOTE = '"';
public static final char SINGLE_QUOTE = '\'';
public static final char DOT = '.';
public static final String DOT_STR = ".";
public static final char ARRAY_START = '[';
public static final String ARRAY_START_STR = "[";
public static final char ARRAY_SEPRATOR = ',';
public static final String ARRAY_SEPRATOR_STR = ",";
public static final char ARRAY_END = ']';
public static final String ARRAY_END_STR = "]";
public static final String SPACE_STR = " ";
public static final char SPACE = ' ';
public static final char BLOCK_START = '{';
public static final String BLOCK_START_STR = "{";
public static final char BLOCK_END = '}';
public static final String BLOCK_END_STR = "}";
public static final char DOLLAR = '$';
public static final String DOLLAR_STR = "$";
/**
* condition
* */
public static final char CONDITION_IF = '?';
public static final String CONDITION_IF_STRING = "?";
public static final char CONDITION_IF_MIDDLE = ':';
/**
* match
* */
public static final String PLUS ="+";
public static final String SUB = "-";
public static final String MUL = "*";
public static final String DIV = "/";
public static final String MOD = "%";
public static final String AND = "&&";
public static final String OR = "||";
/**
* and operator
* */
public static final String EQUAL = "===";
public static final String EQUAL2 = "==";
public static final String NOT_EQUAL = "!==";
public static final String NOT_EQUAL2 = "!=";
public static final String AND_NOT = "!";
public static final String G = ">";
public static final String GE = ">=";
public static final String LE = "<=";
public static final String L = "<";
/**
* https://github.com/jquery/esprima/blob/master/src/parser.ts
* */
public static Map<String, Integer> OPERATORS_PRIORITY = new HashMap<>();
static {
OPERATORS_PRIORITY.put(BLOCK_END_STR, 0);
OPERATORS_PRIORITY.put(BRACKET_END_STR, 0);
OPERATORS_PRIORITY.put(SPACE_STR, 0);
OPERATORS_PRIORITY.put(ARRAY_SEPRATOR_STR, 0);
OPERATORS_PRIORITY.put(ARRAY_END_STR, 0);
OPERATORS_PRIORITY.put(OR, 1);
OPERATORS_PRIORITY.put(AND, 1);
OPERATORS_PRIORITY.put(EQUAL, 2);
OPERATORS_PRIORITY.put(EQUAL2, 2);
OPERATORS_PRIORITY.put(NOT_EQUAL, 2);
OPERATORS_PRIORITY.put(NOT_EQUAL2, 2);
OPERATORS_PRIORITY.put(G, 7);
OPERATORS_PRIORITY.put(GE, 7);
OPERATORS_PRIORITY.put(L, 7);
OPERATORS_PRIORITY.put(LE, 8);
OPERATORS_PRIORITY.put(PLUS, 9);
OPERATORS_PRIORITY.put(SUB, 9);
OPERATORS_PRIORITY.put(MUL, 10);
OPERATORS_PRIORITY.put(DIV, 10);
OPERATORS_PRIORITY.put(MOD, 10);
OPERATORS_PRIORITY.put(AND_NOT, 11);
OPERATORS_PRIORITY.put(DOT_STR, 15);
OPERATORS_PRIORITY.put(ARRAY_START_STR, 16);
OPERATORS_PRIORITY.put(BRACKET_START_STR, 17);
OPERATORS_PRIORITY.put(BLOCK_START_STR, 17);
}
public static final Map<String,Object> KEYWORDS = new HashMap<>();
static {
KEYWORDS.put("null", null);
KEYWORDS.put("true", Boolean.TRUE);
KEYWORDS.put("false", Boolean.FALSE);
KEYWORDS.put("undefined", null);
}
}