/** * 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; }
/** * Transfomiert eine Not (not) Operation. Im Gegensatz zu CFMX , wird das "!" Zeichen auch als Not * Operator anerkannt. <br> * EBNF:<br> * <code>[("not"|"!") spaces] decsionOp; (* "!" Existiert in CFMX nicht *)</code> * * @return CFXD Element * @throws PageException */ private Ref notOp() throws PageException { if (cfml.isValidIndex()) { if (cfml.isCurrent('!') && !cfml.isCurrent("!=")) { cfml.next(); cfml.removeSpace(); return new Not(decsionOp()); } else if (cfml.forwardIfCurrentAndNoWordAfter("not")) { cfml.removeSpace(); return new Not(decsionOp()); } } return decsionOp(); }
/** * 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; }
/** * 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()); }
protected Ref json(FunctionLibFunction flf, char start, char end) throws PageException { // print.out("start:"+start+":"+cfml.getCurrent()); if (!cfml.isCurrent(start)) return null; Ref[] args = functionArg(flf.getName(), false, flf, end); // if (!cfml.forwardIfCurrent(end)) // throw new ExpressionException("Invalid Syntax Closing ["+end+"] not found"); return new BIFCall(pc, flf, args); }
/** * Transfomiert eine Konkatinations-Operator (&) Operation. Im Gegensatz zu CFMX , wird das "!" * Zeichen auch als Not Operator anerkannt. <br> * EBNF:<br> * <code>plusMinusOp {"&" spaces concatOp};</code> * * @return CFXD Element * @throws PageException */ private Ref concatOp() throws PageException { Ref ref = plusMinusOp(); while (cfml.isCurrent('&') && !cfml.isNext('&')) { cfml.next(); ref = _concat(ref); // cfml.removeSpace(); // ref=new Concat(pc,ref,plusMinusOp()); } return ref; }
/** * Extrahiert den Start Element einer Variale, dies ist entweder eine Funktion, eine Scope * Definition oder eine undefinierte Variable. <br> * EBNF:<br> * <code>identifier "(" functionArg ")" | scope | identifier;</code> * * @param name Einstiegsname * @return CFXD Element * @throws PageException */ private Ref startElement(String name) throws PageException { // check function if (cfml.isCurrent('(')) { FunctionLibFunction function = fld.getFunction(name); Ref[] arguments = functionArg(name, true, function, ')'); // print.out(name+":"+(function!=null)); if (function != null) return new BIFCall(pc, function, arguments); Ref ref = new railo.runtime.interpreter.ref.var.Scope(pc, Scope.SCOPE_UNDEFINED); return new UDFCall(pc, ref, name, arguments); } // check scope return scope(name); }
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 "); }
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; }
/** * Hier werden die verschiedenen Mglichen Werte erkannt und jenachdem wird mit der passenden * Methode weitergefahren <br> * EBNF:<br> * <code>string | number | dynamic | sharp;</code> * * @return CFXD Element * @throws PageException */ private Ref checker() throws PageException { Ref ref = null; // String if (cfml.isCurrentQuoter()) { // mode=STATIC; is at the end of the string function because must set after execution return string(); } // Number if (cfml.isCurrentDigit() || cfml.isCurrent('.')) { // mode=STATIC; is at the end of the string function because must set after execution return number(); } // Dynamic if ((ref = dynamic()) != null) { mode = DYNAMIC; return ref; } // Sharp if ((ref = sharp()) != null) { mode = DYNAMIC; return ref; } // JSON if ((ref = json(JSON_ARRAY, '[', ']')) != null) { mode = DYNAMIC; return ref; } if ((ref = json(JSON_STRUCT, '{', '}')) != null) { mode = DYNAMIC; return ref; } if (cfml.isAfterLast() && cfml.toString().trim().length() == 0) return new LString(""); // else Error throw new ExpressionException( "Syntax Error, Invalid Construct", "at position " + cfml.getPos() + " in [" + cfml.toString() + "]"); }
private Ref _minus(Ref ref) throws PageException { // -= if (cfml.isCurrent('=')) { cfml.next(); cfml.removeSpace(); Ref right = assignOp(); Ref res = new Minus(ref, right); ref = new Assign(ref, res); } /*/ -- else if (cfml.isCurrent('-')) { cfml.next(); cfml.removeSpace(); Ref res = new Minus(ref,new LNumber(new Double(1))); ref=new Assign(ref,res); ref=new Plus(ref,new LNumber(new Double(1))); }*/ else { cfml.removeSpace(); ref = new Minus(ref, modOp()); } return ref; }
/** * <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; }
/** * 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()]); }