private Ref unaryOp() throws PageException { Ref ref = negateMinusOp(); if (cfml.forwardIfCurrent("--")) ref = _unaryOp(ref, false); else if (cfml.forwardIfCurrent("++")) ref = _unaryOp(ref, true); return ref; }
/** * Transfomiert einen numerische Wert. Die L¦nge des numerischen Wertes interessiert nicht zu * ᅵbersetzungszeit, ein "Overflow" fhrt zu einem Laufzeitfehler. Da die zu erstellende CFXD, * bzw. dieser Transfomer, keine Vorwegnahme des Laufzeitsystems vornimmt. <br> * EBNF:<br> * <code>["+"|"-"] digit {digit} {"." digit {digit}};</code> * * @return CFXD Element * @throws PageException */ private Ref number() throws PageException { // check first character is a number literal representation // if(!cfml.isCurrentDigit()) return null; StringBuffer rtn = new StringBuffer(6); // get digit on the left site of the dot if (cfml.isCurrent('.')) rtn.append('0'); else digit(rtn); // read dot if exist if (cfml.forwardIfCurrent('.')) { rtn.append('.'); int before = cfml.getPos(); digit(rtn); if (before < cfml.getPos() && cfml.forwardIfCurrent('e')) { if (cfml.isCurrentDigit()) { rtn.append('e'); digit(rtn); } else { cfml.previous(); } } // read right side of the dot if (before == cfml.getPos()) throw new ExpressionException("Number can't end with [.]"); // rtn.append(rightSite); } cfml.removeSpace(); mode = STATIC; return new LNumber(rtn.toString()); }
/** * Transfomiert eine Or (or) Operation. Im Gegensatz zu CFMX , werden "||" Zeichen auch als Or * Operatoren anerkannt. <br> * EBNF:<br> * <code>andOp {("or" | "||") spaces andOp}; (* "||" Existiert in CFMX nicht *)</code> * * @return CFXD Element * @throws PageException */ private Ref orOp() throws PageException { Ref ref = andOp(); while (cfml.isValidIndex() && (cfml.forwardIfCurrent("||") || cfml.forwardIfCurrent("or"))) { cfml.removeSpace(); ref = new Or(ref, andOp()); } return ref; }
/** * Liest einen gelableten Funktionsparamter ein <br> * EBNF:<br> * <code>assignOp [":" spaces assignOp];</code> * * @return CFXD Element * @throws PageException */ private Ref functionArgDeclaration() throws PageException { Ref ref = impOp(); if (cfml.forwardIfCurrent(':') || cfml.forwardIfCurrent('=')) { cfml.removeSpace(); ref = new LFunctionValue(ref, assignOp()); } return ref; }
/** * Transfomiert eine And (and) Operation. Im Gegensatz zu CFMX , werden "&&" Zeichen auch als And * Operatoren anerkannt. <br> * EBNF:<br> * <code>notOp {("and" | "&&") spaces notOp}; (* "&&" Existiert in CFMX nicht *)</code> * * @return CFXD Element * @throws PageException */ private Ref andOp() throws PageException { Ref ref = notOp(); while (cfml.isValidIndex() && (cfml.forwardIfCurrent("&&") || cfml.forwardIfCurrent("and"))) { cfml.removeSpace(); ref = new And(ref, notOp()); } return ref; }
/** * Transfomiert den Exponent Operator (^,exp). Im Gegensatz zu CFMX , werden die Zeichen " exp " * auch als Exponent anerkannt. <br> * EBNF:<br> * <code>clip {("exp"|"^") spaces clip};</code> * * @return CFXD Element * @throws PageException */ private Ref expoOp() throws PageException { Ref ref = unaryOp(); while (cfml.isValidIndex() && (cfml.forwardIfCurrent('^') || cfml.forwardIfCurrent("exp"))) { cfml.removeSpace(); ref = new Exp(ref, unaryOp()); } return ref; }
/** * Sharps (#) die innerhalb von Expressions auftauchen haben in CFML keine weitere Beteutung und * werden durch diese Methode einfach entfernt. <br> * Beispiel:<br> * <code>arrayLen(#arr#)</code> und <code>arrayLen(arr)</code> sind identisch. EBNF:<br> * <code>"#" checker "#";</code> * * @return CFXD Element * @throws PageException */ private Ref sharp() throws PageException { if (!cfml.forwardIfCurrent('#')) return null; Ref ref; cfml.removeSpace(); ref = assignOp(); cfml.removeSpace(); if (!cfml.forwardIfCurrent('#')) throw new ExpressionException("Syntax Error, Invalid Construct"); cfml.removeSpace(); return ref; }
/** * Transfomiert eine Modulus Operation. Im Gegensatz zu CFMX , wird das "%" Zeichen auch als * Modulus Operator anerkannt. <br> * EBNF:<br> * <code> * divMultiOp {("mod" | "%") spaces divMultiOp}; (* modulus operator , "%" Existiert in CFMX nicht *) * </code> * * @return CFXD Element * @throws PageException */ private Ref modOp() throws PageException { Ref ref = divMultiOp(); while (cfml.isValidIndex() && (cfml.forwardIfCurrent('%') || cfml.forwardIfCurrent("mod"))) { ref = _mod(ref); // cfml.removeSpace(); // ref=new Mod(ref,divMultiOp()); } return ref; }
private Ref contOp() throws PageException { Ref ref = impOp(); while (cfml.forwardIfCurrent('?')) { cfml.removeSpace(); Ref left = assignOp(); if (!cfml.forwardIfCurrent(':')) throw new ExpressionException( "Syntax Error, invalid conditional operator [" + cfml.toString() + "]"); cfml.removeSpace(); Ref right = assignOp(); ref = new Cont(ref, left, right); } return ref; }
/** * Liest den folgenden idetifier ein und prft ob dieser ein boolscher Wert ist. Im Gegensatz zu * CFMX wird auch "yes" und "no" als bolscher <wert akzeptiert, was bei CFMX nur beim Umwandeln * einer Zeichenkette zu einem boolschen Wert der Fall ist.<br> * Wenn es sich um keinen bolschen Wert handelt wird der folgende Wert eingelesen mit seiner * ganzen Hirarchie. <br> * EBNF:<br> * <code>"true" | "false" | "yes" | "no" | startElement * {("." identifier | "[" structElement "]" )[function] };</code> * * @return CFXD Element * @throws PageException */ private Ref dynamic() throws PageException { // Die Implementation weicht ein wenig von der Grammatik ab, // aber nicht in der Logik sondern rein wie es umgesetzt wurde. // get First Element of the Variable String name = identifier(false); if (name == null) { if (!cfml.forwardIfCurrent('(')) return null; cfml.removeSpace(); Ref ref = assignOp(); if (!cfml.forwardIfCurrent(')')) throw new ExpressionException("Invalid Syntax Closing [)] not found"); cfml.removeSpace(); return subDynamic(ref); } // Element el; cfml.removeSpace(); char first = name.charAt(0); // Boolean constant if (first == 'T' && name.equals("TRUE")) { cfml.removeSpace(); return LBoolean.TRUE; } else if (first == 'F' && name.equals("FALSE")) { cfml.removeSpace(); return LBoolean.FALSE; } else if (first == 'Y' && name.equals("YES")) { cfml.removeSpace(); return LBoolean.TRUE; } else if (first == 'N') { if (name.equals("NO")) { cfml.removeSpace(); return LBoolean.FALSE; } else if (allowNullConstant && name.equals("NULL")) { cfml.removeSpace(); return new LString(null); } else if (name.equals("NEW")) { Ref res = newOp(); if (res != null) return res; } } // Extract Scope from the Variable // Object value = startElement(name); return subDynamic(startElement(name)); }
/** * Transfomiert die mathematischen Operatoren Mal und Durch (*,/). <br> * EBNF:<br> * <code>expoOp {("*"|"/") spaces expoOp};</code> * * @return CFXD Element * @throws PageException */ private Ref divMultiOp() throws PageException { Ref ref = expoOp(); while (!cfml.isLast()) { // Multiply Operation if (cfml.forwardIfCurrent('*')) { ref = _multi(ref); // cfml.removeSpace(); // ref=new Multi(ref,expoOp()); } // Divide Operation else if (cfml.isCurrent('/') && (!cfml.isCurrent("/>"))) { cfml.next(); ref = _div(ref); // cfml.removeSpace(); // ref=new Div(ref,expoOp()); } // Divide Operation else if (cfml.isCurrent('\\')) { cfml.next(); ref = _intdiv(ref); // cfml.removeSpace(); // ref=new IntDiv(ref,expoOp()); } else { break; } } return ref; }
private Ref subDynamic(Ref ref) throws PageException { String name = null; // Loop over nested Variables while (cfml.isValidIndex()) { // . if (cfml.forwardIfCurrent('.')) { // Extract next Var String cfml.removeSpace(); name = identifier(true); if (name == null) throw new ExpressionException("Invalid identifier"); cfml.removeSpace(); ref = new Variable(pc, ref, name); } // [] else if (cfml.forwardIfCurrent('[')) { cfml.removeSpace(); ref = new Variable(pc, ref, assignOp()); cfml.removeSpace(); if (!cfml.forwardIfCurrent(']')) throw new ExpressionException("Invalid Syntax Closing []] not found"); } // finish else { break; } cfml.removeSpace(); if (cfml.isCurrent('(')) { if (!(ref instanceof Set)) throw new ExpressionException( "invalid syntax " + ref.getTypeName() + " can't called as function"); Set set = (Set) ref; ref = new UDFCall(pc, set.getParent(), set.getKey(), functionArg(name, false, null, ')')); } } if (ref instanceof railo.runtime.interpreter.ref.var.Scope) { railo.runtime.interpreter.ref.var.Scope s = (railo.runtime.interpreter.ref.var.Scope) ref; if (s.getScope() == Scope.SCOPE_ARGUMENTS || s.getScope() == Scope.SCOPE_LOCAL || s.getScope() == ScopeSupport.SCOPE_VAR) { ref = new Bind(s); } } return ref; }
/** * Transfomiert eine Xor (xor) Operation. <br> * EBNF:<br> * <code>orOp {"xor" spaces orOp};</code> * * @return CFXD Element * @throws PageException */ private Ref xorOp() throws PageException { Ref ref = orOp(); while (cfml.forwardIfCurrent("xor")) { cfml.removeSpace(); ref = new Xor(ref, orOp()); } return ref; }
/** * Transfomiert eine Equivalence (eqv) Operation. <br> * EBNF:<br> * <code>xorOp {"eqv" spaces xorOp};</code> * * @return CFXD Element * @throws PageException */ private Ref eqvOp() throws PageException { Ref ref = xorOp(); while (cfml.forwardIfCurrent("eqv")) { cfml.removeSpace(); ref = new EQV(ref, xorOp()); } return ref; }
/** * Transfomiert die mathematischen Operatoren Plus und Minus (1,-). <br> * EBNF:<br> * <code>modOp [("-"|"+") spaces plusMinusOp];</code> * * @return CFXD Element * @throws PageException */ private Ref plusMinusOp() throws PageException { Ref ref = modOp(); while (!cfml.isLast()) { // Plus Operation if (cfml.forwardIfCurrent('+')) { ref = _plus(ref); // cfml.removeSpace(); // ref=new Plus(ref,modOp()); } // Minus Operation else if (cfml.forwardIfCurrent('-')) { ref = _minus(ref); // cfml.removeSpace(); // ref=new Minus(ref,modOp()); } else break; } return ref; }
private Ref _multi(Ref ref) throws PageException { // \= if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); Ref right = assignOp(); Ref res = new Multi(ref, right); ref = new Assign(ref, res); } else { cfml.removeSpace(); ref = new Multi(ref, expoOp()); } return ref; }
private Ref _concat(Ref ref) throws PageException { // &= if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); Ref right = assignOp(); Ref res = new Concat(pc, ref, right); ref = new Assign(ref, res); } else { cfml.removeSpace(); ref = new Concat(pc, ref, plusMinusOp()); } return ref; }
/** * Transfomiert Zuweisungs Operation. <br> * EBNF:<br> * <code>eqvOp ["=" spaces assignOp];</code> * * @return CFXD Element * @throws PageException */ protected Ref assignOp() throws PageException { Ref ref = contOp(); if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); if (mode == STATIC || ref instanceof Literal) { ref = new DynAssign(pc, ref, assignOp()); } else { ref = new Assign(ref, assignOp()); } } return ref; }
/** * Transfomiert einen lierale Zeichenkette. <br> * EBNF:<br> * <code>("'" {"##"|"''"|"#" impOp "#"| ?-"#"-"'" } "'") | * (""" {"##"|""""|"#" impOp "#"| ?-"#"-""" } """);</code> * * @return CFXD Element * @throws PageException */ protected Ref string() throws PageException { // Init Parameter char quoter = cfml.getCurrentLower(); // String str=""; LStringBuffer str = new LStringBuffer(); Ref value = null; while (cfml.hasNext()) { cfml.next(); // check sharp if (cfml.isCurrent('#')) { if (cfml.isNext('#')) { cfml.next(); str.append('#'); } else { cfml.next(); cfml.removeSpace(); if (!str.isEmpty() || value != null) str.append(assignOp()); else value = assignOp(); cfml.removeSpace(); if (!cfml.isCurrent('#')) throw new ExpressionException("Invalid Syntax Closing [#] not found"); } } else if (cfml.isCurrent(quoter)) { if (cfml.isNext(quoter)) { cfml.next(); str.append(quoter); } else { break; } } // all other character else { str.append(cfml.getCurrent()); } } if (!cfml.forwardIfCurrent(quoter)) throw new ExpressionException( "Invalid String Literal Syntax Closing [" + quoter + "] not found"); cfml.removeSpace(); mode = STATIC; if (value != null) { if (str.isEmpty()) return value; return new Concat(pc, value, str); } return str; }
/** * Liest die Vordlobe einer Zahl ein * * @return CFXD Element * @throws PageException */ private Ref negateMinusOp() throws PageException { // And Operation if (cfml.forwardIfCurrent('-')) { if (cfml.forwardIfCurrent('-')) { cfml.removeSpace(); Ref expr = clip(); Minus res = new Minus(expr, new LNumber(new Double(1))); return new Assign(expr, res); } cfml.removeSpace(); return new Negate(clip()); } if (cfml.forwardIfCurrent('+')) { if (cfml.forwardIfCurrent('+')) { cfml.removeSpace(); Ref expr = clip(); Plus res = new Plus(expr, new LNumber(new Double(1))); return new Assign(expr, res); } cfml.removeSpace(); return new Casting(pc, "numeric", CFTypes.TYPE_NUMERIC, clip()); } return clip(); }
private Ref newOp() throws PageException { int start = cfml.getPos(); String name = null; cfml.removeSpace(); // first identifier name = identifier(true); Ref refName = null; if (name != null) { StringBuilder fullName = new StringBuilder(); fullName.append(name); // Loop over addional identifier while (cfml.isValidIndex()) { if (cfml.forwardIfCurrent('.')) { cfml.removeSpace(); name = identifier(true); if (name == null) throw new ExpressionException("invalid Component declaration"); cfml.removeSpace(); fullName.append('.'); fullName.append(name); } else break; } refName = new LString(fullName.toString()); } else { if (cfml.isCurrentQuoter()) refName = string(); if (refName == null) { cfml.setPos(start); return null; } } cfml.removeSpace(); if (cfml.isCurrent('(')) { FunctionLibFunction function = fld.getFunction("_createComponent"); Ref[] arguments = functionArg("_createComponent", true, function, ')'); Ref[] args = new Ref[arguments.length + 1]; for (int i = 0; i < arguments.length; i++) { args[i] = arguments[i]; } args[args.length - 1] = refName; BIFCall bif = new BIFCall(pc, function, args); cfml.removeSpace(); return bif; } throw new ExpressionException("invalid Component declaration "); }
/** * Liest einen gelableten Funktionsparamter ein <br> * EBNF:<br> * <code>assignOp [":" spaces assignOp];</code> * * @return CFXD Element * @throws PageException */ private Ref functionArgDeclarationVarString() throws PageException { cfml.removeSpace(); StringBuffer str = new StringBuffer(); String id = null; while ((id = identifier(false)) != null) { if (str.length() > 0) str.append('.'); str.append(id); cfml.removeSpace(); if (!cfml.forwardIfCurrent('.')) break; cfml.removeSpace(); } cfml.removeSpace(); if (str.length() > 0 && cfml.charAt(cfml.getPos() - 1) != '.') return new LString(str.toString()); throw new ExpressionException("invalid variable name definition"); }
/** * Liest die Argumente eines Funktonsaufruf ein und prft ob die Funktion innerhalb der FLD * (Function Library Descriptor) definiert ist. Falls sie existiert wird die Funktion gegen diese * geprft und ein build-in-function CFXD Element generiert, ansonsten ein normales funcion-call * Element. <br> * EBNF:<br> * <code>[impOp{"," impOp}];</code> * * @param name Identifier der Funktion als Zeichenkette * @param checkLibrary Soll geprft werden ob die Funktion innerhalb der Library existiert. * @param flf FLD Function definition . * @return CFXD Element * @throws PageException */ private Ref[] functionArg(String name, boolean checkLibrary, FunctionLibFunction flf, char end) throws PageException { // get Function Library checkLibrary = checkLibrary && flf != null; // Function Attributes ArrayList arr = new ArrayList(); ArrayList arrFuncLibAtt = null; int libLen = 0; if (checkLibrary) { arrFuncLibAtt = flf.getArg(); libLen = arrFuncLibAtt.size(); } int count = 0; do { cfml.next(); cfml.removeSpace(); // finish if (cfml.isCurrent(end)) break; // too many Attributes boolean isDynamic = false; int max = -1; if (checkLibrary) { isDynamic = isDynamic(flf); max = flf.getArgMax(); // Dynamic if (isDynamic) { if (max != -1 && max <= count) throw new ExpressionException("too many Attributes in function [" + name + "]"); } // Fix else { if (libLen <= count) throw new ExpressionException("too many Attributes in function [" + name + "]"); } } if (checkLibrary && !isDynamic) { // current attribues from library FunctionLibFunctionArg funcLibAtt = (FunctionLibFunctionArg) arrFuncLibAtt.get(count); short type = CFTypes.toShort(funcLibAtt.getType(), CFTypes.TYPE_UNKNOW); if (type == CFTypes.TYPE_VARIABLE_STRING) { arr.add(functionArgDeclarationVarString()); } else { arr.add(new Casting(pc, funcLibAtt.getTypeAsString(), type, functionArgDeclaration())); } } else { arr.add(functionArgDeclaration()); } // obj=andOrXor(); cfml.removeSpace(); count++; } while (cfml.isCurrent(',')); // end with ) ?? if (!cfml.forwardIfCurrent(end)) { if (name.startsWith("_json")) throw new ExpressionException("Invalid Syntax Closing [" + end + "] not found"); throw new ExpressionException( "Invalid Syntax Closing [" + end + "] for function [" + name + "] not found"); } // check min attributes if (checkLibrary && flf.getArgMin() > count) throw new ExpressionException("to less Attributes in function [" + name + "]"); cfml.removeSpace(); return (Ref[]) arr.toArray(new Ref[arr.size()]); }
/** * <font f>Transfomiert eine Vergleichs Operation. <br> * EBNF:<br> * <code>concatOp {("neq"|"eq"|"gte"|"gt"|"lte"|"lt"|"ct"| * "contains"|"nct"|"does not contain") spaces concatOp}; * (* "ct"=conatains und "nct"=does not contain; Existiert in CFMX nicht *)</code> * * @return CFXD Element * @throws PageException */ private Ref decsionOp() throws PageException { Ref ref = concatOp(); boolean hasChanged = false; // ct, contains if (cfml.isValidIndex()) { do { hasChanged = false; if (cfml.isCurrent('c')) { if (cfml.forwardIfCurrent("ct")) { cfml.removeSpace(); ref = new CT(ref, concatOp()); hasChanged = true; } else if (cfml.forwardIfCurrent("contains")) { cfml.removeSpace(); ref = new CT(ref, concatOp()); hasChanged = true; } } // does not contain else if (cfml.forwardIfCurrent("does", "not", "contain")) { cfml.removeSpace(); ref = new NCT(ref, concatOp()); hasChanged = true; } // equal, eq else if (cfml.isCurrent("eq") && !cfml.isCurrent("eqv")) { cfml.setPos(cfml.getPos() + 2); cfml.forwardIfCurrent("ual"); cfml.removeSpace(); ref = new EQ(ref, concatOp()); hasChanged = true; } // == else if (cfml.forwardIfCurrent("==")) { if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); ref = new EEQ(ref, concatOp()); } else { cfml.removeSpace(); ref = new EQ(ref, concatOp()); } hasChanged = true; } // != else if (cfml.forwardIfCurrent("!=")) { if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); ref = new NEEQ(ref, concatOp()); } else { cfml.removeSpace(); ref = new NEQ(ref, concatOp()); } hasChanged = true; } // <=/</<> else if (cfml.forwardIfCurrent('<')) { if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); ref = new LTE(ref, concatOp()); } else if (cfml.forwardIfCurrent('>')) { cfml.removeSpace(); ref = new NEQ(ref, concatOp()); } else { cfml.removeSpace(); ref = new LT(ref, concatOp()); } hasChanged = true; } // >/>= else if (cfml.forwardIfCurrent('>')) { if (cfml.forwardIfCurrent('=')) { cfml.removeSpace(); ref = new GTE(ref, concatOp()); } else { cfml.removeSpace(); ref = new GT(ref, concatOp()); } hasChanged = true; } // gt, gte, greater than or equal to, greater than else if (cfml.isCurrent('g')) { if (cfml.forwardIfCurrent("gt")) { if (cfml.forwardIfCurrent('e')) { cfml.removeSpace(); ref = new GTE(ref, concatOp()); } else { cfml.removeSpace(); ref = new GT(ref, concatOp()); } hasChanged = true; } else if (cfml.forwardIfCurrent("greater", "than")) { if (cfml.forwardIfCurrent("or", "equal", "to", true)) { cfml.removeSpace(); ref = new GTE(ref, concatOp()); } else { cfml.removeSpace(); ref = new GT(ref, concatOp()); } hasChanged = true; } else if (cfml.forwardIfCurrent("ge")) { cfml.removeSpace(); ref = new GTE(ref, concatOp()); hasChanged = true; } } // is, is not else if (cfml.forwardIfCurrent("is")) { if (cfml.forwardIfCurrent("not", true)) { cfml.removeSpace(); ref = new NEQ(ref, concatOp()); } else { cfml.removeSpace(); ref = new EQ(ref, concatOp()); } hasChanged = true; } // lt, lte, less than, less than or equal to else if (cfml.isCurrent('l')) { if (cfml.forwardIfCurrent("lt")) { if (cfml.forwardIfCurrent('e')) { cfml.removeSpace(); ref = new LTE(ref, concatOp()); } else { cfml.removeSpace(); ref = new LT(ref, concatOp()); } hasChanged = true; } else if (cfml.forwardIfCurrent("less", "than")) { if (cfml.forwardIfCurrent("or", "equal", "to", true)) { cfml.removeSpace(); ref = new LTE(ref, concatOp()); } else { cfml.removeSpace(); ref = new LT(ref, concatOp()); } hasChanged = true; } else if (cfml.forwardIfCurrent("le")) { cfml.removeSpace(); ref = new LTE(ref, concatOp()); hasChanged = true; } } // neq, not equal, nct else if (cfml.isCurrent('n')) { // Not Equal if (cfml.forwardIfCurrent("neq")) { cfml.removeSpace(); ref = new NEQ(ref, concatOp()); hasChanged = true; } // Not Equal (Alias) else if (cfml.forwardIfCurrent("not", "equal")) { cfml.removeSpace(); ref = new NEQ(ref, concatOp()); hasChanged = true; } // nct else if (cfml.forwardIfCurrent("nct")) { cfml.removeSpace(); ref = new NCT(ref, concatOp()); hasChanged = true; } } } while (hasChanged); } return ref; }