package org.develnext.jphp.core.tokenizer.token.expr; import org.develnext.jphp.core.tokenizer.TokenType; import org.develnext.jphp.core.tokenizer.TokenMeta; import org.develnext.jphp.core.tokenizer.token.Token; import org.develnext.jphp.core.tokenizer.token.expr.operator.*; import org.develnext.jphp.core.tokenizer.token.expr.value.*; import org.develnext.jphp.core.tokenizer.token.stmt.ExprStmtToken; abstract public class ValueExprToken extends ExprToken { public ValueExprToken(TokenMeta meta, TokenType type) { super(meta, type); } public boolean isConstant(){ return false; } public Object toNumeric(){ return 0L; } protected ValueExprToken operatorResult(Object value){ if (value instanceof String) return new StringExprToken(TokenMeta.of(value.toString(), this), StringExprToken.Quote.SINGLE); else if (value instanceof Long) return new IntegerExprToken(TokenMeta.of(value.toString(), this)); else if (value instanceof Double) return new DoubleExprToken(TokenMeta.of(value.toString(), this)); else if (value instanceof Boolean) return new BooleanExprToken(TokenMeta.of((Boolean)value ? "true" : "false", this)); else return null; } protected ValueExprToken plus(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); if (o1 instanceof Long && o2 instanceof Long) return operatorResult((Long)o1 + (Long)o2); else return operatorResult(Double.valueOf(o1.toString()) + Double.valueOf(o2.toString())); } protected ValueExprToken minus(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); if (o1 instanceof Long && o2 instanceof Long) return operatorResult((Long)o1 - (Long)o2); else return operatorResult(Double.valueOf(o1.toString()) - Double.valueOf(o2.toString())); } protected ValueExprToken mul(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); if (o1 instanceof Long && o2 instanceof Long) return operatorResult((Long)o1 * (Long)o2); else return operatorResult(Double.valueOf(o1.toString()) * Double.valueOf(o2.toString())); } protected ValueExprToken pow(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); return operatorResult(Math.pow(Double.valueOf(o1.toString()), Double.valueOf(o2.toString()))); } protected ValueExprToken div(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); double r = (Double.valueOf(o1.toString()) / Double.valueOf(o2.toString())); if (r == Math.floor(r) && !Double.isInfinite(r)) return operatorResult((long)r); else return operatorResult(r); } protected ValueExprToken mod(ValueExprToken value){ Object o1 = this.toNumeric(); Object o2 = value.toNumeric(); if (o1 instanceof Long && o2 instanceof Long) return operatorResult((Long)o1 % (Long)o2); else return operatorResult(Double.valueOf(o1.toString()) % Double.valueOf(o2.toString())); } protected ValueExprToken concat(ValueExprToken value){ return operatorResult(this.toString() + value.toString()); } public ValueExprToken operator(ValueExprToken value, OperatorExprToken operator){ if (operator instanceof PlusExprToken) return plus(value); else if (operator instanceof MinusExprToken) return minus(value); else if (operator instanceof MulExprToken) return mul(value); else if (operator instanceof DivExprToken) return div(value); else if (operator instanceof PowExprToken) return pow(value); else if (operator instanceof ModExprToken) return mod(value); else if (operator instanceof ConcatExprToken) return concat(value); else return null; } public static boolean isConstable(Token token, boolean arrays){ if (token instanceof NameToken) return true; if (token instanceof IntegerExprToken) return true; if (token instanceof DoubleExprToken) return true; if (token instanceof StringExprToken){ if (((StringExprToken) token).getSegments().isEmpty()) return true; } if (token instanceof StaticAccessExprToken) { StaticAccessExprToken sa = (StaticAccessExprToken) token; if (!sa.isGetStaticField() && (sa.getClazz() instanceof NameToken || sa.getClazz() instanceof SelfExprToken)) { return true; } } if (arrays){ if (token instanceof ArrayExprToken){ ArrayExprToken array = (ArrayExprToken) token; for(ExprStmtToken e : array.getParameters()){ if (e.isSingle()){ if (!isConstable(e.getSingle(), true)) return false; } else if (e.getTokens().size() == 3) { if (e.getTokens().get(1) instanceof KeyValueExprToken){ if (isConstable(e.getSingle(), false) && isConstable(e.getLast(), true)) continue; } return false; } else return false; } return true; } } return false; } }