docs: private Expression decsionOp(Data data) throws TemplateException {
  
  	Expression expr = concatOp(data);
  	boolean hasChanged = false;
  	// ct, contains
  	do {
  	    hasChanged = false;
  	    if (data.srcCode.isCurrent('c')) {
  		if (data.srcCode.forwardIfCurrent("ct", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_CT, expr);
  		    hasChanged = true;
  		}
  		else if (data.srcCode.forwardIfCurrent("contains", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_CT, expr);
  		    hasChanged = true;
  		}
  	    }
  	    // does not contain
  	    else if (data.srcCode.forwardIfCurrent("does", "not", "contain", false, true)) {
  		expr = decisionOpCreate(data, Factory.OP_DEC_NCT, expr);
  		hasChanged = true;
  	    }
  
  	    // equal, eq
  	    else if (data.srcCode.isCurrent("eq") && !data.srcCode.isCurrent("eqv")) {
  		int plus = 2;
  		data.srcCode.setPos(data.srcCode.getPos() + 2);
  		if (data.srcCode.forwardIfCurrent("ual")) plus = 5;
  
  		if (data.srcCode.isCurrentVariableCharacter()) {
  		    data.srcCode.setPos(data.srcCode.getPos() - plus);
  		}
  		else {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_EQ, expr);
  		    hasChanged = true;
  		}
  
  	    }
  	    // ==
  	    else if (data.srcCode.forwardIfCurrent("==")) {
  		if (data.srcCode.forwardIfCurrent('=')) expr = decisionOpCreate(data, Factory.OP_DEC_EEQ, expr);
  		else expr = decisionOpCreate(data, Factory.OP_DEC_EQ, expr);
  		hasChanged = true;
  	    }
  	    // !=
  	    else if (data.srcCode.forwardIfCurrent("!=")) {
  		if (data.srcCode.forwardIfCurrent('=')) expr = decisionOpCreate(data, Factory.OP_DEC_NEEQ, expr);
  		else expr = decisionOpCreate(data, Factory.OP_DEC_NEQ, expr);
  		hasChanged = true;
  	    }
  	    // <=/</<>
  	    else if (data.srcCode.isCurrent('<')) {
  		hasChanged = true;
  		if (data.srcCode.isNext('=')) {
  		    data.srcCode.next();
  		    data.srcCode.next();
  		    expr = decisionOpCreate(data, Factory.OP_DEC_LTE, expr);
  		}
  		else if (data.srcCode.isNext('>')) {
  		    data.srcCode.next();
  		    data.srcCode.next();
  		    expr = decisionOpCreate(data, Factory.OP_DEC_NEQ, expr);
  		}
  		else if (data.srcCode.isNext('/')) {
  		    hasChanged = false;
  		}
  		else {
  		    data.srcCode.next();
  		    expr = decisionOpCreate(data, Factory.OP_DEC_LT, expr);
  		}
  	    }
  	    // >=/>
  	    else if (data.allowLowerThan && data.srcCode.forwardIfCurrent('>')) {
  		if (data.srcCode.forwardIfCurrent('=')) expr = decisionOpCreate(data, Factory.OP_DEC_GTE, expr);
  		else expr = decisionOpCreate(data, Factory.OP_DEC_GT, expr);
  		hasChanged = true;
  	    }
  
  	    // gt, gte, greater than or equal to, greater than
  	    else if (data.srcCode.isCurrent('g')) {
  		if (data.srcCode.forwardIfCurrent("gt")) {
  		    if (data.srcCode.forwardIfCurrentAndNoWordAfter("e")) {
  			if (data.srcCode.isCurrentVariableCharacter()) {
  			    data.srcCode.setPos(data.srcCode.getPos() - 3);
  			}
  			else {
  			    expr = decisionOpCreate(data, Factory.OP_DEC_GTE, expr);
  			    hasChanged = true;
  			}
  		    }
  		    else {
  			if (data.srcCode.isCurrentVariableCharacter()) {
  			    data.srcCode.setPos(data.srcCode.getPos() - 2);
  			}
  			else {
  			    expr = decisionOpCreate(data, Factory.OP_DEC_GT, expr);
  			    hasChanged = true;
  			}
  		    }
  		}
  		else if (data.srcCode.forwardIfCurrent("greater", "than", false, true)) {
  		    if (data.srcCode.forwardIfCurrent("or", "equal", "to", true, true)) expr = decisionOpCreate(data, Factory.OP_DEC_GTE, expr);
  		    else expr = decisionOpCreate(data, Factory.OP_DEC_GT, expr);
  		    hasChanged = true;
  		}
  		else if (data.srcCode.forwardIfCurrent("ge", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_GTE, expr);
  		    hasChanged = true;
  		}
  	    }
  
  	    // is, is not
  	    else if (data.srcCode.forwardIfCurrent("is", false, true)) {
  		if (data.srcCode.forwardIfCurrent("not", true, true)) expr = decisionOpCreate(data, Factory.OP_DEC_NEQ, expr);
  		else expr = decisionOpCreate(data, Factory.OP_DEC_EQ, expr);
  		hasChanged = true;
  	    }
  
  	    // lt, lte, less than, less than or equal to
  	    else if (data.srcCode.isCurrent('l')) {
  		if (data.srcCode.forwardIfCurrent("lt")) {
  		    if (data.srcCode.forwardIfCurrentAndNoWordAfter("e")) {
  			if (data.srcCode.isCurrentVariableCharacter()) {
  			    data.srcCode.setPos(data.srcCode.getPos() - 3);
  			}
  			else {
  			    expr = decisionOpCreate(data, Factory.OP_DEC_LTE, expr);
  			    hasChanged = true;
  			}
  		    }
  		    else {
  			if (data.srcCode.isCurrentVariableCharacter()) {
  			    data.srcCode.setPos(data.srcCode.getPos() - 2);
  			}
  			else {
  			    expr = decisionOpCreate(data, Factory.OP_DEC_LT, expr);
  			    hasChanged = true;
  			}
  		    }
  		}
  		else if (data.srcCode.forwardIfCurrent("less", "than", false, true)) {
  		    if (data.srcCode.forwardIfCurrent("or", "equal", "to", true, true)) expr = decisionOpCreate(data, Factory.OP_DEC_LTE, expr);
  		    else expr = decisionOpCreate(data, Factory.OP_DEC_LT, expr);
  		    hasChanged = true;
  		}
  		else if (data.srcCode.forwardIfCurrent("le", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_LTE, expr);
  		    hasChanged = true;
  		}
  	    }
  
  	    // neq, not equal, nct
  	    else if (data.srcCode.isCurrent('n')) {
  		// Not Equal
  		if (data.srcCode.forwardIfCurrent("neq", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_NEQ, expr);
  		    hasChanged = true;
  		}
  		// Not Equal (Alias)
  		else if (data.srcCode.forwardIfCurrent("not", "equal", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_NEQ, expr);
  		    hasChanged = true;
  		}
  		// nct
  		else if (data.srcCode.forwardIfCurrent("nct", false, true)) {
  		    expr = decisionOpCreate(data, Factory.OP_DEC_NCT, expr);
  		    hasChanged = true;
  		}
  	    }
  
  	}
  	while (hasChanged);
  	return expr;
      }