in src/main/java/org/apache/commons/jexl3/internal/TemplateScript.java [68:151]
public TemplateScript(final TemplateEngine engine,
final JexlInfo jexlInfo,
final String directive,
final Reader reader,
final String... parms) {
if (directive == null) {
throw new NullPointerException("null prefix");
}
final String engineImmediateCharString = Character.toString(engine.getImmediateChar());
final String engineDeferredCharString = Character.toString(engine.getDeferredChar());
if (engineImmediateCharString.equals(directive)
|| engineDeferredCharString.equals(directive)
|| (engineImmediateCharString + "{").equals(directive)
|| (engineDeferredCharString + "{").equals(directive)) {
throw new IllegalArgumentException(directive + ": is not a valid directive pattern");
}
if (reader == null) {
throw new NullPointerException("null input");
}
this.jxlt = engine;
this.prefix = directive;
final List<Block> blocks = jxlt.readTemplate(prefix, reader);
final List<TemplateExpression> uexprs = new ArrayList<>();
final StringBuilder strb = new StringBuilder();
int nuexpr = 0;
int codeStart = -1;
int line = 1;
for (int b = 0; b < blocks.size(); ++b) {
final Block block = blocks.get(b);
final int bl = block.getLine();
while(line < bl) {
strb.append("//\n");
line += 1;
}
if (block.getType() == BlockType.VERBATIM) {
strb.append("jexl:print(");
strb.append(nuexpr++);
strb.append(");\n");
line += 1;
} else {
// keep track of first block of code, the frame creator
if (codeStart < 0) {
codeStart = b;
}
final String body = block.getBody();
strb.append(body);
for(int c = 0; c < body.length(); ++c) {
if (body.charAt(c) == '\n') {
line += 1;
}
}
}
}
// create the script
final JexlInfo info = jexlInfo == null ? jxlt.getEngine().createInfo() : jexlInfo;
// allow lambda defining params
final Scope scope = parms == null ? null : new Scope(null, parms);
script = jxlt.getEngine().parse(info.at(1, 1), false, strb.toString(), scope).script();
// seek the map of expression number to scope so we can parse Unified
// expression blocks with the appropriate symbols
final Map<Integer, JexlNode.Info> minfo = new TreeMap<>();
collectPrintScope(script.script(), minfo);
// jexl:print(...) expression counter
int jpe = 0;
// create the exprs using the intended scopes
for (final Block block : blocks) {
if (block.getType() == BlockType.VERBATIM) {
final JexlNode.Info ji = minfo.get(jpe);
TemplateExpression te;
// no node info means this verbatim is surrounded by comments markers;
// expr at this index is never called
if (ji != null) {
te = jxlt.parseExpression(ji, block.getBody(), scopeOf(ji));
} else {
te = jxlt.new ConstantExpression(block.getBody(), null);
}
uexprs.add(te);
jpe += 1;
}
}
source = blocks.toArray(new Block[0]);
exprs = uexprs.toArray(new TemplateExpression[0]);
}