docs: private boolean tag(Data data, Body parent) throws TemplateException {
  	boolean startingParseExpression = data.parseExpression;
  	ExprTransformer startingTransformer = data.transformer;
  	try {
  	    boolean hasBody = false;
  
  	    Position line = data.srcCode.getPosition();
  	    // int column=data.cfml.getColumn();
  	    int start = data.srcCode.getPos();
  	    data.srcCode.next();
  
  	    // read in namespace of tag
  	    TagLib tagLib = nameSpace(data);
  
  	    // return if no matching tag lib
  	    if (tagLib == null) {
  		data.srcCode.previous();
  		return false;
  	    }
  
  	    // Get matching tag from tag lib
  	    String strNameNormal = identifier(data.srcCode, false, true);
  	    if (strNameNormal == null) {
  		data.srcCode.setPos((data.srcCode.getPos() - tagLib.getNameSpaceAndSeparator().length()) - 1);
  		return false;
  	    }
  
  	    String strName = strNameNormal.toLowerCase();
  	    String appendix = null;
  	    TagLibTag tagLibTag = tagLib.getTag(strName);
  
  	    // get taglib
  	    if (tagLibTag == null) {
  		tagLibTag = tagLib.getAppendixTag(strName);
  		if (tagLibTag == null) {
  		    if (tagLib.getIgnoreUnknowTags()) {
  			data.srcCode.setPos(start);
  			return false;
  		    }
  		    throw new TemplateException(data.srcCode, "undefined tag [" + tagLib.getNameSpaceAndSeparator() + strName + "]");
  		}
  		appendix = StringUtil.removeStartingIgnoreCase(strNameNormal, tagLibTag.getName());
  	    }
  
  	    // CFXD Element
  	    Tag tag;
  	    try {
  		tag = tagLibTag.getTag(data.factory, line, data.srcCode.getPosition());
  	    }
  	    catch (Exception e) {
  		throw new TemplateException(data.srcCode, e);
  	    }
  	    parent.addStatement(tag);
  
  	    // get tag from tag library
  	    if (appendix != null) {
  		tag.setAppendix(appendix);
  		tag.setFullname(tagLibTag.getFullName().concat(appendix));
  	    }
  	    else {
  		tag.setFullname(tagLibTag.getFullName());
  	    }
  	    // if(tag.getFullname().equalsIgnoreCase("cfcomponent"))data.page.setIsComponent(true); // MUST to
  	    // hardcoded, to better
  	    // else if(tag.getFullname().equalsIgnoreCase("cfinterface"))data.page.setIsInterface(true); // MUST
  	    // to hardcoded, to better
  
  	    tag.setTagLibTag(tagLibTag);
  	    comment(data.srcCode, true);
  
  	    // Tag Translator Evaluator
  	    if (tagLibTag.hasTTE()) {
  		data.ep.add(tagLibTag, tag, data.flibs, data.srcCode);
  	    }
  
  	    // get Attributes
  	    attributes(data, tagLibTag, tag);
  
  	    if (tagLibTag.hasAttributeEvaluator()) {
  		try {
  		    tagLibTag = tagLibTag.getAttributeEvaluator().evaluate(tagLibTag, tag);
  		}
  		catch (AttributeEvaluatorException e) {
  
  		    throw new TemplateException(data.srcCode, e);
  		}
  	    }
  
  	    // End of begin Tag
  	    // TODO muss erlaubt sein
  	    if (data.srcCode.forwardIfCurrent('>')) {
  		hasBody = tagLibTag.getHasBody();
  	    }
  	    else if (data.srcCode.forwardIfCurrent('/', '>')) {
  		if (tagLibTag.getHasBody()) tag.setBody(new BodyBase(data.factory));
  	    }
  	    else {
  		throw createTemplateException(data.srcCode, "tag [" + tagLibTag.getFullName() + "] is not closed", tagLibTag);
  	    }
  
  	    // Body
  	    if (hasBody) {
  
  		// get Body
  		if (tagLibTag.isTagDependent()) {
  		    // get TagDependentBodyTransformer
  		    TagDependentBodyTransformer tdbt = null;
  		    try {
  			tdbt = tagLibTag.getBodyTransformer();
  		    }
  		    catch (TagLibException e) {
  			throw new TemplateException(data.srcCode, e);
  		    }
  		    if (tdbt == null) throw createTemplateException(data.srcCode, "Tag dependent body Transformer is invalid for Tag [" + tagLibTag.getFullName() + "]", tagLibTag);
  
  		    // tag.setBody(tdbt.transform(data.factory,data.root,data.ep,data.tlibs,data.flibs,
  		    // tagLibTag.getFullName(),data.scriptTags,data.srcCode,data.settings));
  
  		    tag.setBody(tdbt.transform(data, tagLibTag.getFullName()));
  
  		    // get TagLib of end Tag
  		    if (!data.srcCode.forwardIfCurrent("</")) {
  			// MUST this is a patch, do a more proper implementation
  			TemplateException te = new TemplateException(data.srcCode, "invalid construct");
  			if (tdbt instanceof CFMLScriptTransformer && ASMUtil.containsComponent(tag.getBody())) {
  			    throw new CFMLScriptTransformer.ComponentTemplateException(te);
  			}
  			throw te;
  		    }
  
  		    TagLib tagLibEnd = nameSpace(data);
  		    // same NameSpace
  		    if (!(tagLibEnd != null && tagLibEnd.getNameSpaceAndSeparator().equals(tagLib.getNameSpaceAndSeparator())))
  			throw new TemplateException(data.srcCode, "invalid construct");
  		    // get end Tag
  		    String strNameEnd = identifier(data.srcCode, true, true).toLowerCase();
  
  		    // not the same name Tag
  		    if (!strName.equals(strNameEnd)) {
  			data.srcCode.setPos(start);
  			throw new TemplateException(data.srcCode, "Start and End Tag has not the same Name [" + tagLib.getNameSpaceAndSeparator() + strName + "-"
  				+ tagLibEnd.getNameSpaceAndSeparator() + strNameEnd + "]");
  		    }
  		    data.srcCode.removeSpace();
  		    if (!data.srcCode.forwardIfCurrent('>'))
  			throw new TemplateException(data.srcCode, "End Tag [" + tagLibEnd.getNameSpaceAndSeparator() + strNameEnd + "] not closed");
  		}
  		else {
  		    // get body of Tag
  		    BodyBase body = new BodyBase(data.factory);
  		    body.setParent(tag);
  		    // tag.setBody(body);
  		    // parseExpression=(tagLibTag.getParseBody())?true:parseExpression;
  		    if (tagLibTag.getParseBody()) data.parseExpression = true;
  
  		    while (true) {
  
  			// Load Expession Transformer from TagLib
  			data.transformer = startingTransformer;
  			if (data.parseExpression) {
  			    try {
  				data.transformer = tagLibTag.getTagLib().getExprTransfomer();
  			    }
  			    catch (TagLibException e) {
  				throw new TemplateException(data.srcCode, e);
  			    }
  			}
  
  			// call body
  
  			body(data, body);
  
  			// no End Tag
  			if (done || data.srcCode.isAfterLast()) {
  
  			    if (tagLibTag.isBodyReq()) {
  				data.srcCode.setPos(start);
  				throw createTemplateException(data.srcCode, "No matching end tag found for tag [" + tagLibTag.getFullName() + "]", tagLibTag);
  			    }
  			    body.moveStatmentsTo(parent);
  			    return executeEvaluator(data, tagLibTag, tag);
  			}
  
  			// Invalid Construct
  			int posBeforeEndTag = data.srcCode.getPos();
  			if (!data.srcCode.forwardIfCurrent('<', '/'))
  			    throw createTemplateException(data.srcCode, "Missing end tag for [" + tagLibTag.getFullName() + "]", tagLibTag);
  
  			// get TagLib of end Tag
  			int _start = data.srcCode.getPos();
  			TagLib tagLibEnd = nameSpace(data);
  
  			// same NameSpace
  			if (tagLibEnd != null) {
  			    String strNameEnd = "";
  			    // lucee.print.ln(data.cfml.getLine()+" - "+data.cfml.getColumn()+" -
  			    // "+tagLibEnd.getNameSpaceAndSeperator()+".equals("+tagLib.getNameSpaceAndSeperator()+")");
  			    if (tagLibEnd.getNameSpaceAndSeparator().equals(tagLib.getNameSpaceAndSeparator())) {
  
  				// get end Tag
  				strNameEnd = identifier(data.srcCode, true, true).toLowerCase();
  				// not the same name Tag
  
  				// new part
  				data.srcCode.removeSpace();
  				if (strName.equals(strNameEnd)) {
  				    if (!data.srcCode.forwardIfCurrent('>'))
  					throw new TemplateException(data.srcCode, "End Tag [" + tagLibEnd.getNameSpaceAndSeparator() + strNameEnd + "] not closed");
  				    break;
  				}
  
  			    }
  			    // new part
  			    if (tagLibTag.isBodyReq()) {
  				TagLibTag endTag = tagLibEnd.getTag(strNameEnd);
  				if (endTag != null && !endTag.getHasBody()) throw new TemplateException(data.srcCode,
  					"End Tag [" + tagLibEnd.getNameSpaceAndSeparator() + strNameEnd + "] is not allowed, for this tag only a Start Tag is allowed");
  				data.srcCode.setPos(start);
  				if (tagLibEnd.getIgnoreUnknowTags() && (tagLibEnd.getTag(strNameEnd)) == null) {
  				    data.srcCode.setPos(_start);
  				}
  				else throw new TemplateException(data.srcCode, "Start and End Tag has not the same Name [" + tagLib.getNameSpaceAndSeparator() + strName + "-"
  					+ tagLibEnd.getNameSpaceAndSeparator() + strNameEnd + "]");
  			    }
  			    else {
  				body.moveStatmentsTo(parent);
  				data.srcCode.setPos(posBeforeEndTag);
  				return executeEvaluator(data, tagLibTag, tag);
  			    }
  			    /// new part
  			}
  			body.addPrintOut(data.factory, "</", null, null);
  
  		    }
  		    tag.setBody(body);
  
  		}
  	    }
  	    if (tag instanceof StatementBase) ((StatementBase) tag).setEnd(data.srcCode.getPosition());
  	    // Tag Translator Evaluator
  
  	    return executeEvaluator(data, tagLibTag, tag);
  	}
  	finally {
  	    data.parseExpression = startingParseExpression;
  	    data.transformer = startingTransformer;
  	}
      }