use of lucee.runtime.exp.TemplateException in project Lucee by lucee.
the class CFMLTransformer method attributes.
/**
* Liest die Attribute eines Tags ein, dies Abhaengig von der Definition innerhalb der Tag-Lib.
* Hierbei unterscheiden wir vier verschiedene Arten von Attributen:<br>
* <ul>
* <li>FIX: Definierte Attribute Fix, fuer jedes Attribut ist definiert ob es required ist oder nicht (gleich wie JSP). </li>
* <li>DYNAMIC: Die Attribute des Tag sind frei, keine Namen sind vorgegeben.
* Es kann aber definiert sein wieviele Attribute maximal und minimal verwendetet werden duerfen.</li>
* <li>FULLDYNAMIC: Gleich wie DYNAMIC, jedoch kann der Name des Attribut auch ein dynamischer Wert sein (wie bei cfset).</li>
* <li>NONAME: Ein Tag welches nur ein Attribut besitzt ohne Name, sondern einfach nur mit einem Attribut Wert</li>
* </ul>
* <br />
* EBNF:<br />
* <code>({spaces attribute} "/>" | {spaces attribute} ">") | attribute-value;(* Welcher Teil der "oder" Bedingung ausgefuehrt wird, ist abhaengig von der Tag Attribute Definition in der Tag Lib. *)</code>
* @param tag
* @param parent
* @throws TemplateException
*/
public static void attributes(TagData data, TagLibTag tag, Tag parent) throws TemplateException {
int type = tag.getAttributeType();
int start = data.srcCode.getPos();
// Tag with attribute names
if (type != TagLibTag.ATTRIBUTE_TYPE_NONAME) {
try {
int min = tag.getMin();
int max = tag.getMax();
int count = 0;
ArrayList<String> args = new ArrayList<String>();
RefBoolean allowDefaultValue = new RefBooleanImpl(tag.getDefaultAttribute() != null);
while (data.srcCode.isValidIndex()) {
data.srcCode.removeSpace();
// if no more attributes break
if (data.srcCode.isCurrent('/') || data.srcCode.isCurrent('>'))
break;
parent.addAttribute(attribute(data, tag, args, allowDefaultValue));
count++;
}
// set default values
if (tag.hasDefaultValue()) {
Map<String, TagLibTagAttr> hash = tag.getAttributes();
Iterator<Entry<String, TagLibTagAttr>> it = hash.entrySet().iterator();
Entry<String, TagLibTagAttr> e;
TagLibTagAttr att;
while (it.hasNext()) {
e = it.next();
att = e.getValue();
if (!parent.containsAttribute(att.getName()) && att.hasDefaultValue()) {
Attribute attr = new Attribute(tag.getAttributeType() == TagLibTag.ATTRIBUTE_TYPE_DYNAMIC, att.getName(), CastOther.toExpression(data.factory.createLitString(Caster.toString(att.getDefaultValue(), null)), att.getType()), att.getType());
attr.setDefaultAttribute(true);
parent.addAttribute(attr);
}
}
}
boolean hasAttributeCollection = args.contains("attributecollection");
// to less attributes
if (!hasAttributeCollection && min > count)
throw createTemplateException(data.srcCode, "the tag " + tag.getFullName() + " must have at least " + min + " attributes", tag);
// too much attributes
if (!hasAttributeCollection && max > 0 && max < count)
throw createTemplateException(data.srcCode, "the tag " + tag.getFullName() + " can have a maximum of " + max + " attributes", tag);
// not defined attributes
if (type == TagLibTag.ATTRIBUTE_TYPE_FIXED || type == TagLibTag.ATTRIBUTE_TYPE_MIXED) {
// Map<String, TagLibTagAttr> hash = tag.getAttributes();
Iterator<TagLibTagAttr> it = tag.getAttributes().values().iterator();
while (it.hasNext()) {
TagLibTagAttr att = it.next();
if (att.isRequired() && !contains(args, att) && att.getDefaultValue() == null) {
if (!hasAttributeCollection)
throw createTemplateException(data.srcCode, "attribute " + att.getName() + " is required for tag " + tag.getFullName(), tag);
parent.addMissingAttribute(att);
}
}
}
} catch (TemplateException te) {
data.srcCode.setPos(start);
// if the tag supports a non name attribute try this
TagLibTagAttr sa = tag.getSingleAttr();
if (sa != null)
attrNoName(parent, tag, data, sa);
else
throw te;
}
} else // tag without attributes name
{
attrNoName(parent, tag, data, null);
}
}
use of lucee.runtime.exp.TemplateException in project Lucee by lucee.
the class AbstrCFMLExprTransformer method number.
/**
* Transfomiert einen numerische Wert.
* Die Laenge des numerischen Wertes interessiert nicht zu uebersetzungszeit,
* ein "Overflow" fuehrt 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 TemplateException
*/
private LitDouble number(ExprData data) throws TemplateException {
// check first character is a number literal representation
if (!(data.srcCode.isCurrentBetween('0', '9') || data.srcCode.isCurrent('.')))
return null;
Position line = data.srcCode.getPosition();
StringBuffer rtn = new StringBuffer();
// get digit on the left site of the dot
if (data.srcCode.isCurrent('.'))
rtn.append('0');
else
rtn.append(digit(data));
// read dot if exist
if (data.srcCode.forwardIfCurrent('.')) {
rtn.append('.');
String rightSite = digit(data);
if (rightSite.length() > 0 && data.srcCode.forwardIfCurrent('e')) {
Boolean expOp = null;
if (data.srcCode.forwardIfCurrent('+'))
expOp = Boolean.TRUE;
else if (data.srcCode.forwardIfCurrent('-'))
expOp = Boolean.FALSE;
if (data.srcCode.isCurrentBetween('0', '9')) {
if (expOp == Boolean.FALSE)
rightSite += "e-";
else if (expOp == Boolean.TRUE)
rightSite += "e+";
else
rightSite += "e";
rightSite += digit(data);
} else {
if (expOp != null)
data.srcCode.previous();
data.srcCode.previous();
}
}
// read right side of the dot
if (rightSite.length() == 0)
// throw new TemplateException(cfml, "Number can't end with [.]"); // DIFF 23
rightSite = "0";
rtn.append(rightSite);
} else // scientific notation
if (data.srcCode.forwardIfCurrent('e')) {
Boolean expOp = null;
if (data.srcCode.forwardIfCurrent('+'))
expOp = Boolean.TRUE;
else if (data.srcCode.forwardIfCurrent('-'))
expOp = Boolean.FALSE;
if (data.srcCode.isCurrentBetween('0', '9')) {
String rightSite = "e";
if (expOp == Boolean.FALSE)
rightSite += "-";
else if (expOp == Boolean.TRUE)
rightSite += "+";
rightSite += digit(data);
rtn.append(rightSite);
} else {
if (expOp != null)
data.srcCode.previous();
data.srcCode.previous();
}
}
comments(data);
try {
return data.factory.createLitDouble(Caster.toDoubleValue(rtn.toString()), line, data.srcCode.getPosition());
} catch (CasterException e) {
throw new TemplateException(data.srcCode, e.getMessage());
}
}
use of lucee.runtime.exp.TemplateException in project Lucee by lucee.
the class AbstrCFMLExprTransformer method multiLineComment.
/**
* Liest einen Mehrzeiligen Kommentar ein.
* <br />
* EBNF:<br />
* <code>?-"*<!-- -->/";</code>
* @return bool Wurde ein Kommentar entfernt?
* @throws TemplateException
*/
private boolean multiLineComment(ExprData data) throws TemplateException {
SourceCode cfml = data.srcCode;
if (!cfml.forwardIfCurrent("/*"))
return false;
int pos = cfml.getPos();
boolean isDocComment = cfml.isCurrent('*');
while (cfml.isValidIndex()) {
if (cfml.isCurrent("*/"))
break;
cfml.next();
}
if (!cfml.forwardIfCurrent("*/")) {
cfml.setPos(pos);
throw new TemplateException(cfml, "comment is not closed");
}
if (isDocComment) {
String comment = cfml.substring(pos - 2, cfml.getPos() - pos);
data.docComment = docCommentTransformer.transform(data.factory, comment);
}
return true;
}
use of lucee.runtime.exp.TemplateException in project Lucee by lucee.
the class AbstrCFMLExprTransformer method simple.
/**
* @param data
* @return parsed Element
* @throws TemplateException
*/
private Expression simple(ExprData data, String[] breakConditions) throws TemplateException {
StringBuffer sb = new StringBuffer();
Position line = data.srcCode.getPosition();
outer: while (data.srcCode.isValidIndex()) {
for (int i = 0; i < breakConditions.length; i++) {
if (data.srcCode.isCurrent(breakConditions[i]))
break outer;
}
if (data.srcCode.isCurrent('"') || data.srcCode.isCurrent('#') || data.srcCode.isCurrent('\'')) {
throw new TemplateException(data.srcCode, "simple attribute value can't contain [" + data.srcCode.getCurrent() + "]");
}
sb.append(data.srcCode.getCurrent());
data.srcCode.next();
}
comments(data);
return data.factory.createLitString(sb.toString(), line, data.srcCode.getPosition());
}
use of lucee.runtime.exp.TemplateException in project Lucee by lucee.
the class AbstrCFMLExprTransformer method getFunctionMember.
/**
* Liest die Argumente eines Funktonsaufruf ein und prueft ob die Funktion
* innerhalb der FLD (Function Library Descriptor) definiert ist.
* Falls sie existiert wird die Funktion gegen diese geprueft 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 geprueft werden ob die Funktion innerhalb der Library existiert.
* @return CFXD Element
* @throws TemplateException
*/
private FunctionMember getFunctionMember(ExprData data, final ExprString name, boolean checkLibrary) throws TemplateException {
// get Function Library
checkLibrary = checkLibrary && data.flibs != null;
FunctionLibFunction flf = null;
if (checkLibrary) {
if (!(name instanceof Literal))
// should never happen!
throw new TemplateException(data.srcCode, "syntax error");
for (int i = 0; i < data.flibs.length; i++) {
flf = data.flibs[i].getFunction(((Literal) name).getString());
if (flf != null)
break;
}
if (flf == null) {
checkLibrary = false;
}
}
FunctionMember fm = null;
while (true) {
int pos = data.srcCode.getPos();
// Element Function
if (checkLibrary) {
BIF bif = new BIF(data.factory, data.settings, flf);
// TODO data.ep.add(flf, bif, data.srcCode);
bif.setArgType(flf.getArgType());
try {
bif.setClassDefinition(flf.getFunctionClassDefinition());
} catch (Throwable t) {
ExceptionUtil.rethrowIfNecessary(t);
throw new PageRuntimeException(t);
}
bif.setReturnType(flf.getReturnTypeAsString());
fm = bif;
if (flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC && flf.hasDefaultValues()) {
ArrayList<FunctionLibFunctionArg> args = flf.getArg();
Iterator<FunctionLibFunctionArg> it = args.iterator();
FunctionLibFunctionArg arg;
while (it.hasNext()) {
arg = it.next();
if (arg.getDefaultValue() != null)
bif.addArgument(new NamedArgument(data.factory.createLitString(arg.getName()), data.factory.createLitString(arg.getDefaultValue()), arg.getTypeAsString(), false));
}
}
} else {
fm = new UDF(name);
}
int count = getFunctionMemberAttrs(data, name, checkLibrary, fm, flf);
if (checkLibrary) {
// pre
if (flf.hasTteClass()) {
FunctionLibFunction tmp = flf.getEvaluator().pre((BIF) fm, flf);
if (tmp != null && tmp != flf) {
flf = tmp;
data.srcCode.setPos(pos);
continue;
}
}
// check max attributes
{
boolean isDynamic = flf.getArgType() == FunctionLibFunction.ARG_DYNAMIC;
int max = flf.getArgMax();
// Dynamic
if (isDynamic) {
if (max != -1 && max < fm.getArguments().length)
throw new TemplateException(data.srcCode, "too many Attributes (" + max + ":" + fm.getArguments().length + ") in function [ " + ASMUtil.display(name) + " ]");
} else // Fix
{
if (flf.getArg().size() < fm.getArguments().length) {
TemplateException te = new TemplateException(data.srcCode, "too many Attributes (" + flf.getArg().size() + ":" + fm.getArguments().length + ") in function call [" + ASMUtil.display(name) + "]");
UDFUtil.addFunctionDoc(te, flf);
throw te;
}
}
}
// check min attributes
if (flf.getArgMin() > count) {
TemplateException te = new TemplateException(data.srcCode, "too few attributes in function [" + ASMUtil.display(name) + "]");
if (flf.getArgType() == FunctionLibFunction.ARG_FIX)
UDFUtil.addFunctionDoc(te, flf);
throw te;
}
// evaluator
if (flf.hasTteClass()) {
flf.getEvaluator().execute((BIF) fm, flf);
}
}
comments(data);
if (checkLibrary)
data.ep.add(flf, (BIF) fm, data.srcCode);
break;
}
return fm;
}
Aggregations