freemarker.core.FMParser Maven / Gradle / Ivy
Show all versions of freemarker Show documentation
/* FMParser.java */
/* Generated By:JavaCC: Do not edit this line. FMParser.java */
package freemarker.core;
import freemarker.template.*;
import freemarker.template.utility.*;
import java.io.*;
import java.util.*;
/**
* This class is generated by JavaCC from a grammar file.
*/
public class FMParser implements FMParserConstants {
private static final int ITERATOR_BLOCK_KIND_LIST = 0;
private static final int ITERATOR_BLOCK_KIND_FOREACH = 1;
private static final int ITERATOR_BLOCK_KIND_ITEMS = 2;
private static final int ITERATOR_BLOCK_KIND_USER_DIRECTIVE = 3;
private static class ParserIteratorBlockContext {
/**
* loopVarName in <#list ... as loopVarName> or <#items as loopVarName>; null after we left the nested
* block of #list or #items, respectively.
*/
private String loopVarName;
/**
* loopVar1Name in <#list ... as k, loopVar2Name> or <#items as k, loopVar2Name>; null after we left the nested
* block of #list or #items, respectively.
*/
private String loopVar2Name;
/**
* See the ITERATOR_BLOCK_KIND_... costants.
*/
private int kind;
/**
* Is this a key-value pair listing? When there's a nested #items, it's only set there.
*/
private boolean hashListing;
}
private Template template;
private boolean stripWhitespace, stripText, preventStrippings;
private int incompatibleImprovements;
private OutputFormat outputFormat;
private int autoEscapingPolicy;
private boolean autoEscaping;
private ParserConfiguration pCfg;
/** Keeps track of #list and #foreach nesting. */
private List iteratorBlockContexts;
/**
* Keeps track of the nesting depth of directives that support #break.
*/
private int breakableDirectiveNesting;
/**
* Keeps track of the nesting depth of directives that support #continue.
*/
private int continuableDirectiveNesting;
private boolean inMacro, inFunction;
private LinkedList escapes = new LinkedList();
private int mixedContentNesting; // for stripText
/**
* Create an FM expression parser using a string.
*
* @Deprecated This is an internal API of FreeMarker; can be removed any time.
*/
static public FMParser createExpressionParser(String s) {
SimpleCharStream scs = new SimpleCharStream(new StringReader(s), 1, 1, s.length());
FMParserTokenManager token_source = new FMParserTokenManager(scs);
token_source.SwitchTo(FMParserConstants.FM_EXPRESSION);
FMParser parser = new FMParser(token_source);
token_source.setParser(parser);
return parser;
}
/**
* Constructs a new parser object.
*
* @param template
* The template associated with this parser.
* @param reader
* The character stream to use as input
* @param strictEscapeSyntax
* Whether FreeMarker directives must start with a #
*
* @Deprecated This is an internal API of FreeMarker; will be removed in 2.4.
*/
public FMParser(Template template, Reader reader, boolean strictEscapeSyntax, boolean stripWhitespace) {
this(template, reader, strictEscapeSyntax, stripWhitespace, Configuration.AUTO_DETECT_TAG_SYNTAX);
}
/**
* @Deprecated This is an internal API of FreeMarker; will be changed in 2.4.
*/
public FMParser(Template template, Reader reader, boolean strictEscapeSyntax, boolean stripWhitespace, int tagSyntax) {
this(template, reader, strictEscapeSyntax, stripWhitespace, tagSyntax,
Configuration.PARSED_DEFAULT_INCOMPATIBLE_ENHANCEMENTS);
}
/**
* @Deprecated This is an internal API of FreeMarker; will be changed in 2.4.
*/
public FMParser(Template template, Reader reader, boolean strictEscapeSyntax, boolean stripWhitespace,
int tagSyntax, int incompatibleImprovements) {
this(template, reader, strictEscapeSyntax, stripWhitespace,
tagSyntax, Configuration.AUTO_DETECT_NAMING_CONVENTION, incompatibleImprovements);
}
/**
* @Deprecated This is an internal API of FreeMarker; will be changed in 2.4.
*/
public FMParser(String template) {
this(dummyTemplate(),
new StringReader(template), true, true);
}
private static Template dummyTemplate() {
try {
return new Template(null, new StringReader(""), Configuration.getDefaultConfiguration());
} catch (IOException e) {
throw new RuntimeException("Failed to create dummy template", e);
}
}
/**
* @Deprecated This is an internal API of FreeMarker; will be changed in 2.4.
*/
public FMParser(Template template, Reader reader, boolean strictSyntaxMode, boolean whitespaceStripping,
int tagSyntax, int namingConvention, int incompatibleImprovements) {
this(template, reader,
new LegacyConstructorParserConfiguration(
strictSyntaxMode, whitespaceStripping,
tagSyntax, namingConvention,
template != null ? template.getParserConfiguration().getAutoEscapingPolicy()
: Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY,
template != null ? template.getParserConfiguration().getOutputFormat()
: null,
template != null ? template.getParserConfiguration().getRecognizeStandardFileExtensions()
: null,
template != null ? template.getParserConfiguration().getTabSize()
: null,
new Version(incompatibleImprovements),
template != null ? template.getArithmeticEngine() : null));
}
/**
* @Deprecated This is an internal API of FreeMarker; don't call it from outside FreeMarker.
*
* @since 2.3.24
*/
public FMParser(Template template, Reader reader, ParserConfiguration pCfg) {
this(template, true, readerToTokenManager(reader, pCfg), pCfg);
}
private static FMParserTokenManager readerToTokenManager(Reader reader, ParserConfiguration pCfg) {
SimpleCharStream simpleCharStream = new SimpleCharStream(reader, 1, 1);
simpleCharStream.setTabSize(pCfg.getTabSize());
return new FMParserTokenManager(simpleCharStream);
}
/**
* @Deprecated This is an internal API of FreeMarker; don't call it from outside FreeMarker.
*
* @since 2.3.24
*/
public FMParser(Template template, boolean newTemplate, FMParserTokenManager tkMan, ParserConfiguration pCfg) {
this(tkMan);
NullArgumentException.check(pCfg);
this.pCfg = pCfg;
NullArgumentException.check(template);
this.template = template;
// Hack due to legacy public constructors (removed in 2.4):
if (pCfg instanceof LegacyConstructorParserConfiguration) {
LegacyConstructorParserConfiguration lpCfg = (LegacyConstructorParserConfiguration) pCfg;
lpCfg.setArithmeticEngineIfNotSet(template.getArithmeticEngine());
lpCfg.setAutoEscapingPolicyIfNotSet(template.getConfiguration().getAutoEscapingPolicy());
lpCfg.setOutputFormatIfNotSet(template.getOutputFormat());
lpCfg.setRecognizeStandardFileExtensionsIfNotSet(
template.getParserConfiguration().getRecognizeStandardFileExtensions());
lpCfg.setTabSizeIfNotSet(
template.getParserConfiguration().getTabSize());
}
int incompatibleImprovements = pCfg.getIncompatibleImprovements().intValue();
token_source.incompatibleImprovements = incompatibleImprovements;
this.incompatibleImprovements = incompatibleImprovements;
{
OutputFormat outputFormatFromExt;
if (!pCfg.getRecognizeStandardFileExtensions()
|| (outputFormatFromExt = getFormatFromStdFileExt()) == null) {
autoEscapingPolicy = pCfg.getAutoEscapingPolicy();
outputFormat = pCfg.getOutputFormat();
} else {
// Override it
autoEscapingPolicy = Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY;
outputFormat = outputFormatFromExt;
}
}
recalculateAutoEscapingField();
token_source.setParser(this);
token_source.strictEscapeSyntax = pCfg.getStrictSyntaxMode();
int tagSyntax = pCfg.getTagSyntax();
switch (tagSyntax) {
case Configuration.AUTO_DETECT_TAG_SYNTAX:
token_source.autodetectTagSyntax = true;
break;
case Configuration.ANGLE_BRACKET_TAG_SYNTAX:
token_source.squBracTagSyntax = false;
break;
case Configuration.SQUARE_BRACKET_TAG_SYNTAX:
token_source.squBracTagSyntax = true;
break;
default:
throw new IllegalArgumentException("Illegal argument for tagSyntax: " + tagSyntax);
}
int namingConvention = pCfg.getNamingConvention();
switch (namingConvention) {
case Configuration.AUTO_DETECT_NAMING_CONVENTION:
case Configuration.CAMEL_CASE_NAMING_CONVENTION:
case Configuration.LEGACY_NAMING_CONVENTION:
token_source.initialNamingConvention = namingConvention;
token_source.namingConvention = namingConvention;
break;
default:
throw new IllegalArgumentException("Illegal argument for namingConvention: " + namingConvention);
}
this.stripWhitespace = pCfg.getWhitespaceStripping();
// If this is a Template under construction, we do the below.
// If this is just the enclosing Template for ?eval or such, we must not modify it.
if (newTemplate) {
_TemplateAPI.setAutoEscaping(template, autoEscaping);
_TemplateAPI.setOutputFormat(template, outputFormat);
}
}
void setupStringLiteralMode(FMParser parentParser, OutputFormat outputFormat) {
FMParserTokenManager parentTokenSource = parentParser.token_source;
token_source.initialNamingConvention = parentTokenSource.initialNamingConvention;
token_source.namingConvention = parentTokenSource.namingConvention;
token_source.namingConventionEstabilisher = parentTokenSource.namingConventionEstabilisher;
token_source.SwitchTo(NODIRECTIVE);
this.outputFormat = outputFormat;
recalculateAutoEscapingField();
if (incompatibleImprovements < _TemplateAPI.VERSION_INT_2_3_24) {
// Emulate bug, where the string literal parser haven't inherited the IcI:
incompatibleImprovements = _TemplateAPI.VERSION_INT_2_3_0;
}
// So that loop variable built-ins, like ?index, works inside the interpolations in the string literal:
iteratorBlockContexts = parentParser.iteratorBlockContexts;
}
void tearDownStringLiteralMode(FMParser parentParser) {
// If the naming convention was established inside the string literal, it's inherited by the parent:
FMParserTokenManager parentTokenSource = parentParser.token_source;
parentTokenSource.namingConvention = token_source.namingConvention;
parentTokenSource.namingConventionEstabilisher = token_source.namingConventionEstabilisher;
}
/**
* Used when we need to recreate the source code from the AST (such as for the FM2 to FM3 converter).
*/
void setPreventStrippings(boolean preventStrippings) {
this.preventStrippings = preventStrippings;
}
private OutputFormat getFormatFromStdFileExt() {
String sourceName = template.getSourceName();
if (sourceName == null) {
return null; // Not possible anyway...
}
int ln = sourceName.length();
if (ln < 5) return null;
char c = sourceName.charAt(ln - 5);
if (c != '.') return null;
c = sourceName.charAt(ln - 4);
if (c != 'f' && c != 'F') return null;
c = sourceName.charAt(ln - 3);
if (c != 't' && c != 'T') return null;
c = sourceName.charAt(ln - 2);
if (c != 'l' && c != 'L') return null;
c = sourceName.charAt(ln - 1);
try {
// Note: We get the output formats by name, so that custom overrides take effect.
if (c == 'h' || c == 'H') {
return template.getConfiguration().getOutputFormat(HTMLOutputFormat.INSTANCE.getName());
}
if (c == 'x' || c == 'X') {
return template.getConfiguration().getOutputFormat(XMLOutputFormat.INSTANCE.getName());
}
} catch (UnregisteredOutputFormatException e) {
throw new BugException("Unregistered std format", e);
}
return null;
}
/**
* Updates the {@link #autoEscaping} field based on the {@link #autoEscapingPolicy} and {@link #outputFormat} fields.
*/
private void recalculateAutoEscapingField() {
if (outputFormat instanceof MarkupOutputFormat) {
if (autoEscapingPolicy == Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY) {
autoEscaping = ((MarkupOutputFormat) outputFormat).isAutoEscapedByDefault();
} else if (autoEscapingPolicy == Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY) {
autoEscaping = true;
} else if (autoEscapingPolicy == Configuration.DISABLE_AUTO_ESCAPING_POLICY) {
autoEscaping = false;
} else {
throw new IllegalStateException("Unhandled autoEscaping ENUM: " + autoEscapingPolicy);
}
} else {
autoEscaping = false;
}
}
MarkupOutputFormat getMarkupOutputFormat() {
return outputFormat instanceof MarkupOutputFormat ? (MarkupOutputFormat) outputFormat : null;
}
/**
* Don't use it, unless you are developing FreeMarker itself.
*/
public int _getLastTagSyntax() {
return token_source.squBracTagSyntax
? Configuration.SQUARE_BRACKET_TAG_SYNTAX
: Configuration.ANGLE_BRACKET_TAG_SYNTAX;
}
/**
* Don't use it, unless you are developing FreeMarker itself.
* The naming convention used by this template; if it couldn't be detected so far, it will be the most probable one.
* This could be used for formatting error messages, but not for anything serious.
*/
public int _getLastNamingConvention() {
return token_source.namingConvention;
}
/**
* Throw an exception if the expression passed in is a String Literal
*/
private void notStringLiteral(Expression exp, String expected) throws ParseException {
if (exp instanceof StringLiteral) {
throw new ParseException(
"Found string literal: " + exp + ". Expecting: " + expected,
exp);
}
}
/**
* Throw an exception if the expression passed in is a Number Literal
*/
private void notNumberLiteral(Expression exp, String expected) throws ParseException {
if (exp instanceof NumberLiteral) {
throw new ParseException(
"Found number literal: " + exp.getCanonicalForm() + ". Expecting " + expected,
exp);
}
}
/**
* Throw an exception if the expression passed in is a boolean Literal
*/
private void notBooleanLiteral(Expression exp, String expected) throws ParseException {
if (exp instanceof BooleanLiteral) {
throw new ParseException("Found: " + exp.getCanonicalForm() + ". Expecting " + expected, exp);
}
}
/**
* Throw an exception if the expression passed in is a Hash Literal
*/
private void notHashLiteral(Expression exp, String expected) throws ParseException {
if (exp instanceof HashLiteral) {
throw new ParseException(
"Found hash literal: " + exp.getCanonicalForm() + ". Expecting " + expected,
exp);
}
}
/**
* Throw an exception if the expression passed in is a List Literal
*/
private void notListLiteral(Expression exp, String expected)
throws ParseException
{
if (exp instanceof ListLiteral) {
throw new ParseException(
"Found list literal: " + exp.getCanonicalForm() + ". Expecting " + expected,
exp);
}
}
/**
* Throw an exception if the expression passed in is a literal other than of the numerical type
*/
private void numberLiteralOnly(Expression exp) throws ParseException {
notStringLiteral(exp, "number");
notListLiteral(exp, "number");
notHashLiteral(exp, "number");
notBooleanLiteral(exp, "number");
}
/**
* Throw an exception if the expression passed in is not a string.
*/
private void stringLiteralOnly(Expression exp) throws ParseException {
notNumberLiteral(exp, "string");
notListLiteral(exp, "string");
notHashLiteral(exp, "string");
notBooleanLiteral(exp, "string");
}
/**
* Throw an exception if the expression passed in is a literal other than of the boolean type
*/
private void booleanLiteralOnly(Expression exp) throws ParseException {
notStringLiteral(exp, "boolean (true/false)");
notListLiteral(exp, "boolean (true/false)");
notHashLiteral(exp, "boolean (true/false)");
notNumberLiteral(exp, "boolean (true/false)");
}
private Expression escapedExpression(Expression exp) {
if (!escapes.isEmpty()) {
return ((EscapeBlock) escapes.getFirst()).doEscape(exp);
} else {
return exp;
}
}
private boolean getBoolean(Expression exp, boolean legacyCompat) throws ParseException {
TemplateModel tm = null;
try {
tm = exp.eval(null);
} catch (Exception e) {
throw new ParseException(e.getMessage()
+ "\nCould not evaluate expression: "
+ exp.getCanonicalForm(),
exp,
e);
}
if (tm instanceof TemplateBooleanModel) {
try {
return ((TemplateBooleanModel) tm).getAsBoolean();
} catch (TemplateModelException tme) {
}
}
if (legacyCompat && tm instanceof TemplateScalarModel) {
try {
return StringUtil.getYesNo(((TemplateScalarModel) tm).getAsString());
} catch (Exception e) {
throw new ParseException(e.getMessage()
+ "\nExpecting boolean (true/false), found: " + exp.getCanonicalForm(),
exp);
}
}
throw new ParseException("Expecting boolean (true/false) parameter", exp);
}
void checkCurrentOutputFormatCanEscape(Token start) throws ParseException {
if (!(outputFormat instanceof MarkupOutputFormat)) {
throw new ParseException("The current output format can't do escaping: " + outputFormat,
template, start);
}
}
private ParserIteratorBlockContext pushIteratorBlockContext() {
if (iteratorBlockContexts == null) {
iteratorBlockContexts = new ArrayList(4);
}
ParserIteratorBlockContext newCtx = new ParserIteratorBlockContext();
iteratorBlockContexts.add(newCtx);
return newCtx;
}
private void popIteratorBlockContext() {
iteratorBlockContexts.remove(iteratorBlockContexts.size() - 1);
}
private ParserIteratorBlockContext peekIteratorBlockContext() {
int size = iteratorBlockContexts != null ? iteratorBlockContexts.size() : 0;
return size != 0 ? (ParserIteratorBlockContext) iteratorBlockContexts.get(size - 1) : null;
}
private void checkLoopVariableBuiltInLHO(String loopVarName, Expression lhoExp, Token biName)
throws ParseException {
int size = iteratorBlockContexts != null ? iteratorBlockContexts.size() : 0;
for (int i = size - 1; i >= 0; i--) {
ParserIteratorBlockContext ctx = iteratorBlockContexts.get(i);
if (loopVarName.equals(ctx.loopVarName) || loopVarName.equals(ctx.loopVar2Name)) {
if (ctx.kind == ITERATOR_BLOCK_KIND_USER_DIRECTIVE) {
throw new ParseException(
"The left hand operand of ?" + biName.image
+ " can't be the loop variable of an user defined directive: "
+ loopVarName,
lhoExp);
}
return; // success
}
}
throw new ParseException(
"The left hand operand of ?" + biName.image + " must be a loop variable, "
+ "but there's no loop variable in scope with this name: " + loopVarName,
lhoExp);
}
private String forEachDirectiveSymbol() {
// [2.4] Use camel case as the default
return token_source.namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION ? "#forEach" : "#foreach";
}
// Now the actual parsing code, starting
// with the productions for FreeMarker's
// expression syntax.
/**
* This is the same as OrExpression, since
* the OR is the operator with the lowest
* precedence.
*/
final public Expression Expression() throws ParseException {Expression exp;
exp = OrExpression();
{if ("" != null) return exp;}
throw new Error("Missing return statement in function");
}
/**
* Lowest level expression, a literal, a variable,
* or a possibly more complex expression bounded
* by parentheses.
*/
final public Expression PrimaryExpression() throws ParseException {Expression exp;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case INTEGER:
case DECIMAL:{
exp = NumberLiteral();
break;
}
case OPENING_CURLY_BRACKET:{
exp = HashLiteral();
break;
}
case STRING_LITERAL:
case RAW_STRING:{
exp = StringLiteral(true);
break;
}
case FALSE:
case TRUE:{
exp = BooleanLiteral();
break;
}
case OPEN_BRACKET:{
exp = ListLiteral();
break;
}
case ID:{
exp = Identifier();
break;
}
case OPEN_PAREN:{
exp = Parenthesis();
break;
}
case DOT:{
exp = BuiltinVariable();
break;
}
default:
jj_la1[0] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
label_1:
while (true) {
if (jj_2_1(2147483647)) {
;
} else {
break label_1;
}
exp = AddSubExpression(exp);
}
{if ("" != null) return exp;}
throw new Error("Missing return statement in function");
}
final public Expression Parenthesis() throws ParseException {Expression exp, result;
Token start, end;
start = jj_consume_token(OPEN_PAREN);
exp = Expression();
end = jj_consume_token(CLOSE_PAREN);
result = new ParentheticalExpression(exp);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* A primary expression preceded by zero or
* more unary operators. (The only unary operator we
* currently have is the NOT.)
*/
final public Expression UnaryExpression() throws ParseException {Expression exp, result;
boolean haveNot = false;
Token t = null, start = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case PLUS:
case MINUS:{
result = UnaryPlusMinusExpression();
break;
}
case EXCLAM:{
result = NotExpression();
break;
}
case STRING_LITERAL:
case RAW_STRING:
case FALSE:
case TRUE:
case INTEGER:
case DECIMAL:
case DOT:
case OPEN_BRACKET:
case OPEN_PAREN:
case OPENING_CURLY_BRACKET:
case ID:{
result = PrimaryExpression();
break;
}
default:
jj_la1[1] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression NotExpression() throws ParseException {Token t;
Expression exp, result = null;
ArrayList nots = new ArrayList();
label_2:
while (true) {
t = jj_consume_token(EXCLAM);
nots.add(t);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EXCLAM:{
;
break;
}
default:
jj_la1[2] = jj_gen;
break label_2;
}
}
exp = PrimaryExpression();
for (int i = 0; i < nots.size(); i++) {
result = new NotExpression(exp);
Token tok = (Token) nots.get(nots.size() -i -1);
result.setLocation(template, tok, exp);
exp = result;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression UnaryPlusMinusExpression() throws ParseException {Expression exp, result;
boolean isMinus = false;
Token t;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case PLUS:{
t = jj_consume_token(PLUS);
break;
}
case MINUS:{
t = jj_consume_token(MINUS);
isMinus = true;
break;
}
default:
jj_la1[3] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
exp = PrimaryExpression();
result = new UnaryPlusMinusExpression(exp, isMinus);
result.setLocation(template, t, exp);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression AdditiveExpression() throws ParseException {Expression lhs, rhs, result;
boolean plus;
lhs = MultiplicativeExpression();
result = lhs;
label_3:
while (true) {
if (jj_2_2(2147483647)) {
;
} else {
break label_3;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case PLUS:{
jj_consume_token(PLUS);
plus = true;
break;
}
case MINUS:{
jj_consume_token(MINUS);
plus = false;
break;
}
default:
jj_la1[4] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
rhs = MultiplicativeExpression();
if (plus) {
// plus is treated separately, since it is also
// used for concatenation.
result = new AddConcatExpression(lhs, rhs);
} else {
numberLiteralOnly(lhs);
numberLiteralOnly(rhs);
result = new ArithmeticExpression(lhs, rhs, ArithmeticExpression.TYPE_SUBSTRACTION);
}
result.setLocation(template, lhs, rhs);
lhs = result;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* A unary expression followed by zero or more
* unary expressions with operators in between.
*/
final public Expression MultiplicativeExpression() throws ParseException {Expression lhs, rhs, result;
int operation = ArithmeticExpression.TYPE_MULTIPLICATION;
lhs = UnaryExpression();
result = lhs;
label_4:
while (true) {
if (jj_2_3(2147483647)) {
;
} else {
break label_4;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TIMES:{
jj_consume_token(TIMES);
operation = ArithmeticExpression.TYPE_MULTIPLICATION;
break;
}
case DIVIDE:{
jj_consume_token(DIVIDE);
operation = ArithmeticExpression.TYPE_DIVISION;
break;
}
case PERCENT:{
jj_consume_token(PERCENT);
operation = ArithmeticExpression.TYPE_MODULO;
break;
}
default:
jj_la1[5] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
rhs = UnaryExpression();
numberLiteralOnly(lhs);
numberLiteralOnly(rhs);
result = new ArithmeticExpression(lhs, rhs, operation);
result.setLocation(template, lhs, rhs);
lhs = result;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression EqualityExpression() throws ParseException {Expression lhs, rhs, result;
Token t;
lhs = RelationalExpression();
result = lhs;
if (jj_2_4(2147483647)) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case NOT_EQUALS:{
t = jj_consume_token(NOT_EQUALS);
break;
}
case EQUALS:{
t = jj_consume_token(EQUALS);
break;
}
case DOUBLE_EQUALS:{
t = jj_consume_token(DOUBLE_EQUALS);
break;
}
default:
jj_la1[6] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
rhs = RelationalExpression();
notHashLiteral(lhs, "string");
notHashLiteral(rhs, "string");
notListLiteral(lhs, "string");
notListLiteral(rhs, "string");
result = new ComparisonExpression(lhs, rhs, t.image);
result.setLocation(template, lhs, rhs);
} else {
;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression RelationalExpression() throws ParseException {Expression lhs, rhs, result;
Token t;
lhs = RangeExpression();
result = lhs;
if (jj_2_5(2147483647)) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case NATURAL_GTE:{
t = jj_consume_token(NATURAL_GTE);
break;
}
case ESCAPED_GTE:{
t = jj_consume_token(ESCAPED_GTE);
break;
}
case NATURAL_GT:{
t = jj_consume_token(NATURAL_GT);
break;
}
case ESCAPED_GT:{
t = jj_consume_token(ESCAPED_GT);
break;
}
case LESS_THAN_EQUALS:{
t = jj_consume_token(LESS_THAN_EQUALS);
break;
}
case LESS_THAN:{
t = jj_consume_token(LESS_THAN);
break;
}
default:
jj_la1[7] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
rhs = RangeExpression();
notHashLiteral(lhs, "number");
notHashLiteral(rhs, "number");
notListLiteral(lhs, "number");
notListLiteral(rhs, "number");
notStringLiteral(lhs, "number");
notStringLiteral(rhs, "number");
result = new ComparisonExpression(lhs, rhs, t.image);
result.setLocation(template, lhs, rhs);
} else {
;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression RangeExpression() throws ParseException {Expression lhs, rhs = null, result;
int endType;
Token dotDot = null;
lhs = AdditiveExpression();
result = lhs;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case DOT_DOT:
case DOT_DOT_LESS:
case DOT_DOT_ASTERISK:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case DOT_DOT_LESS:
case DOT_DOT_ASTERISK:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case DOT_DOT_LESS:{
jj_consume_token(DOT_DOT_LESS);
endType = Range.END_EXCLUSIVE;
break;
}
case DOT_DOT_ASTERISK:{
jj_consume_token(DOT_DOT_ASTERISK);
endType = Range.END_SIZE_LIMITED;
break;
}
default:
jj_la1[8] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
rhs = AdditiveExpression();
break;
}
case DOT_DOT:{
dotDot = jj_consume_token(DOT_DOT);
endType = Range.END_UNBOUND;
if (jj_2_6(2147483647)) {
rhs = AdditiveExpression();
endType = Range.END_INCLUSIVE;
} else {
;
}
break;
}
default:
jj_la1[9] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
numberLiteralOnly(lhs);
if (rhs != null) {
numberLiteralOnly(rhs);
}
Range range = new Range(lhs, rhs, endType);
if (rhs != null) {
range.setLocation(template, lhs, rhs);
} else {
range.setLocation(template, lhs, dotDot);
}
result = range;
break;
}
default:
jj_la1[10] = jj_gen;
;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression AndExpression() throws ParseException {Expression lhs, rhs, result;
lhs = EqualityExpression();
result = lhs;
label_5:
while (true) {
if (jj_2_7(2147483647)) {
;
} else {
break label_5;
}
jj_consume_token(AND);
rhs = EqualityExpression();
booleanLiteralOnly(lhs);
booleanLiteralOnly(rhs);
result = new AndExpression(lhs, rhs);
result.setLocation(template, lhs, rhs);
lhs = result;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression OrExpression() throws ParseException {Expression lhs, rhs, result;
lhs = AndExpression();
result = lhs;
label_6:
while (true) {
if (jj_2_8(2147483647)) {
;
} else {
break label_6;
}
jj_consume_token(OR);
rhs = AndExpression();
booleanLiteralOnly(lhs);
booleanLiteralOnly(rhs);
result = new OrExpression(lhs, rhs);
result.setLocation(template, lhs, rhs);
lhs = result;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public ListLiteral ListLiteral() throws ParseException {ArrayList values = new ArrayList();
Token begin, end;
begin = jj_consume_token(OPEN_BRACKET);
values = PositionalArgs();
end = jj_consume_token(CLOSE_BRACKET);
ListLiteral result = new ListLiteral(values);
result.setLocation(template, begin, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression NumberLiteral() throws ParseException {Token op = null, t;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case INTEGER:{
t = jj_consume_token(INTEGER);
break;
}
case DECIMAL:{
t = jj_consume_token(DECIMAL);
break;
}
default:
jj_la1[11] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
String s = t.image;
Expression result = new NumberLiteral(pCfg.getArithmeticEngine().toNumber(s));
Token startToken = (op != null) ? op : t;
result.setLocation(template, startToken, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Identifier Identifier() throws ParseException {Token t;
t = jj_consume_token(ID);
Identifier id = new Identifier(t.image);
id.setLocation(template, t, t);
{if ("" != null) return id;}
throw new Error("Missing return statement in function");
}
final public Expression IdentifierOrStringLiteral() throws ParseException {Expression exp;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
exp = Identifier();
break;
}
case STRING_LITERAL:
case RAW_STRING:{
exp = StringLiteral(false);
break;
}
default:
jj_la1[12] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
{if ("" != null) return exp;}
throw new Error("Missing return statement in function");
}
final public BuiltinVariable BuiltinVariable() throws ParseException {Token dot, name;
dot = jj_consume_token(DOT);
name = jj_consume_token(ID);
BuiltinVariable result = null;
token_source.checkNamingConvention(name);
TemplateModel parseTimeValue;
String nameStr = name.image;
if (nameStr.equals(BuiltinVariable.OUTPUT_FORMAT) || nameStr.equals(BuiltinVariable.OUTPUT_FORMAT_CC)) {
parseTimeValue = new SimpleScalar(outputFormat.getName());
} else if (nameStr.equals(BuiltinVariable.AUTO_ESC) || nameStr.equals(BuiltinVariable.AUTO_ESC_CC)) {
parseTimeValue = autoEscaping ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
} else {
parseTimeValue = null;
}
result = new BuiltinVariable(name, token_source, parseTimeValue);
result.setLocation(template, dot, name);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production that builds up an expression
* using the dot or dynamic key name
* or the args list if this is a method invocation.
*/
final public Expression AddSubExpression(Expression exp) throws ParseException {Expression result = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case DOT:{
result = DotVariable(exp);
break;
}
case OPEN_BRACKET:{
result = DynamicKey(exp);
break;
}
case OPEN_PAREN:{
result = MethodArgs(exp);
break;
}
case BUILT_IN:{
result = BuiltIn(exp);
break;
}
case EXCLAM:
case TERMINATING_EXCLAM:{
result = DefaultTo(exp);
break;
}
case EXISTS:{
result = Exists(exp);
break;
}
default:
jj_la1[13] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression DefaultTo(Expression exp) throws ParseException {Expression rhs = null;
Token t;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERMINATING_EXCLAM:{
t = jj_consume_token(TERMINATING_EXCLAM);
break;
}
case EXCLAM:{
t = jj_consume_token(EXCLAM);
if (jj_2_9(2147483647)) {
rhs = Expression();
} else {
;
}
break;
}
default:
jj_la1[14] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
DefaultToExpression result = new DefaultToExpression(exp, rhs);
if (rhs == null) {
result.setLocation(template, exp, t);
} else {
result.setLocation(template, exp, rhs);
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression Exists(Expression exp) throws ParseException {Token t;
t = jj_consume_token(EXISTS);
ExistsExpression result = new ExistsExpression(exp);
result.setLocation(template, exp, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression BuiltIn(Expression lhoExp) throws ParseException {Token t = null;
BuiltIn result;
ArrayList/**/ args = null;
Token openParen;
Token closeParen;
jj_consume_token(BUILT_IN);
t = jj_consume_token(ID);
token_source.checkNamingConvention(t);
result = BuiltIn.newBuiltIn(incompatibleImprovements, lhoExp, t, token_source);
result.setLocation(template, lhoExp, t);
if (!(result instanceof SpecialBuiltIn)) {
{if ("" != null) return result;}
}
if (result instanceof BuiltInForLoopVariable) {
if (!(lhoExp instanceof Identifier)) {
{if (true) throw new ParseException(
"Expression used as the left hand operand of ?" + t.image
+ " must be a simple loop variable name.", lhoExp);}
}
String loopVarName = ((Identifier) lhoExp).getName();
checkLoopVariableBuiltInLHO(loopVarName, lhoExp, t);
((BuiltInForLoopVariable) result).bindToLoopVariable(loopVarName);
{if ("" != null) return result;}
}
if (result instanceof BuiltInBannedWhenAutoEscaping) {
if (outputFormat instanceof MarkupOutputFormat && autoEscaping) {
{if (true) throw new ParseException(
"Using ?" + t.image + " (legacy escaping) is not allowed when auto-escaping is on with "
+ "a markup output format (" + outputFormat.getName() + "), to avoid double-escaping mistakes.",
template, t);}
}
{if ("" != null) return result;}
}
if (result instanceof MarkupOutputFormatBoundBuiltIn) {
if (!(outputFormat instanceof MarkupOutputFormat)) {
{if (true) throw new ParseException(
"?" + t.image + " can't be used here, as the current output format isn't a markup (escaping) "
+ "format: " + outputFormat, template, t);}
}
((MarkupOutputFormatBoundBuiltIn) result).bindToMarkupOutputFormat((MarkupOutputFormat) outputFormat);
{if ("" != null) return result;}
}
if (result instanceof OutputFormatBoundBuiltIn) {
((OutputFormatBoundBuiltIn) result).bindToOutputFormat(outputFormat, autoEscapingPolicy);
{if ("" != null) return result;}
}
if (result instanceof BuiltInWithParseTimeParameters) {
openParen = jj_consume_token(OPEN_PAREN);
args = PositionalArgs();
closeParen = jj_consume_token(CLOSE_PAREN);
result.setLocation(template, lhoExp, closeParen);
((BuiltInWithParseTimeParameters) result).bindToParameters(args, openParen, closeParen);
{if ("" != null) return result;}
} else {
;
}
// Should have already return-ed
{if (true) throw new AssertionError("Unhandled " + SpecialBuiltIn.class.getName() + " subclass: " + result.getClass());}
throw new Error("Missing return statement in function");
}
/**
* production for when a key is specified by + keyname
*/
final public Expression DotVariable(Expression exp) throws ParseException {Token t;
jj_consume_token(DOT);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
t = jj_consume_token(ID);
break;
}
case TIMES:{
t = jj_consume_token(TIMES);
break;
}
case DOUBLE_STAR:{
t = jj_consume_token(DOUBLE_STAR);
break;
}
case FALSE:
case TRUE:
case LESS_THAN:
case LESS_THAN_EQUALS:
case ESCAPED_GT:
case ESCAPED_GTE:
case IN:
case AS:
case USING:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case LESS_THAN:{
t = jj_consume_token(LESS_THAN);
break;
}
case LESS_THAN_EQUALS:{
t = jj_consume_token(LESS_THAN_EQUALS);
break;
}
case ESCAPED_GT:{
t = jj_consume_token(ESCAPED_GT);
break;
}
case ESCAPED_GTE:{
t = jj_consume_token(ESCAPED_GTE);
break;
}
case FALSE:{
t = jj_consume_token(FALSE);
break;
}
case TRUE:{
t = jj_consume_token(TRUE);
break;
}
case IN:{
t = jj_consume_token(IN);
break;
}
case AS:{
t = jj_consume_token(AS);
break;
}
case USING:{
t = jj_consume_token(USING);
break;
}
default:
jj_la1[15] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (!Character.isLetter(t.image.charAt(0))) {
{if (true) throw new ParseException(t.image + " is not a valid identifier.", template, t);}
}
break;
}
default:
jj_la1[16] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
notListLiteral(exp, "hash");
notStringLiteral(exp, "hash");
notBooleanLiteral(exp, "hash");
Dot dot = new Dot(exp, t.image);
dot.setLocation(template, exp, t);
{if ("" != null) return dot;}
throw new Error("Missing return statement in function");
}
/**
* production for when the key is specified
* in brackets.
*/
final public Expression DynamicKey(Expression exp) throws ParseException {Expression arg;
Token t;
jj_consume_token(OPEN_BRACKET);
arg = Expression();
t = jj_consume_token(CLOSE_BRACKET);
notBooleanLiteral(exp, "list or hash");
notNumberLiteral(exp, "list or hash");
DynamicKeyName dkn = new DynamicKeyName(exp, arg);
dkn.setLocation(template, exp, t);
{if ("" != null) return dkn;}
throw new Error("Missing return statement in function");
}
/**
* production for an arglist part of a method invocation.
*/
final public MethodCall MethodArgs(Expression exp) throws ParseException {ArrayList args = new ArrayList();
Token end;
jj_consume_token(OPEN_PAREN);
args = PositionalArgs();
end = jj_consume_token(CLOSE_PAREN);
args.trimToSize();
MethodCall result = new MethodCall(exp, args);
result.setLocation(template, exp, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public StringLiteral StringLiteral(boolean interpolate) throws ParseException {Token t;
boolean raw = false;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STRING_LITERAL:{
t = jj_consume_token(STRING_LITERAL);
break;
}
case RAW_STRING:{
t = jj_consume_token(RAW_STRING);
raw = true;
break;
}
default:
jj_la1[17] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
String s;
// Get rid of the quotes.
if (raw) {
s = t.image.substring(2, t.image.length() -1);
} else {
try {
s = StringUtil.FTLStringLiteralDec(t.image.substring(1, t.image.length() -1));
} catch (ParseException pe) {
pe.lineNumber = t.beginLine;
pe.columnNumber = t.beginColumn;
pe.endLineNumber = t.endLine;
pe.endColumnNumber = t.endColumn;
{if (true) throw pe;}
}
}
StringLiteral result = new StringLiteral(s);
result.setLocation(template, t, t);
if (interpolate && !raw) {
// TODO: This logic is broken. It can't handle literals that contains both ${...} and $\{...}.
if (t.image.indexOf("${") >= 0 || t.image.indexOf("#{") >= 0) result.parseValue(this, outputFormat);
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Expression BooleanLiteral() throws ParseException {Token t;
Expression result;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case FALSE:{
t = jj_consume_token(FALSE);
result = new BooleanLiteral(false);
break;
}
case TRUE:{
t = jj_consume_token(TRUE);
result = new BooleanLiteral(true);
break;
}
default:
jj_la1[18] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
result.setLocation(template, t, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public HashLiteral HashLiteral() throws ParseException {Token begin, end;
Expression key, value;
ArrayList keys = new ArrayList();
ArrayList values = new ArrayList();
begin = jj_consume_token(OPENING_CURLY_BRACKET);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STRING_LITERAL:
case RAW_STRING:
case FALSE:
case TRUE:
case INTEGER:
case DECIMAL:
case DOT:
case PLUS:
case MINUS:
case EXCLAM:
case OPEN_BRACKET:
case OPEN_PAREN:
case OPENING_CURLY_BRACKET:
case ID:{
key = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
case COLON:{
jj_consume_token(COLON);
break;
}
default:
jj_la1[19] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
value = Expression();
stringLiteralOnly(key);
keys.add(key);
values.add(value);
label_7:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
;
break;
}
default:
jj_la1[20] = jj_gen;
break label_7;
}
jj_consume_token(COMMA);
key = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
case COLON:{
jj_consume_token(COLON);
break;
}
default:
jj_la1[21] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
value = Expression();
stringLiteralOnly(key);
keys.add(key);
values.add(value);
}
break;
}
default:
jj_la1[22] = jj_gen;
;
}
end = jj_consume_token(CLOSING_CURLY_BRACKET);
HashLiteral result = new HashLiteral(keys, values);
result.setLocation(template, begin, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* A production representing the ${...}
* that outputs a variable.
*/
final public DollarVariable StringOutput() throws ParseException {Expression exp;
Token begin, end;
begin = jj_consume_token(DOLLAR_INTERPOLATION_OPENING);
exp = Expression();
notHashLiteral(exp, NonStringException.STRING_COERCABLE_TYPES_DESC);
notListLiteral(exp, NonStringException.STRING_COERCABLE_TYPES_DESC);
end = jj_consume_token(CLOSING_CURLY_BRACKET);
DollarVariable result = new DollarVariable(
exp, escapedExpression(exp),
outputFormat,
autoEscaping);
result.setLocation(template, begin, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public NumericalOutput NumericalOutput() throws ParseException {Expression exp;
Token fmt = null, begin, end;
begin = jj_consume_token(HASH_INTERPOLATION_OPENING);
exp = Expression();
numberLiteralOnly(exp);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SEMICOLON:{
jj_consume_token(SEMICOLON);
fmt = jj_consume_token(ID);
break;
}
default:
jj_la1[23] = jj_gen;
;
}
end = jj_consume_token(CLOSING_CURLY_BRACKET);
MarkupOutputFormat> autoEscOF = autoEscaping && outputFormat instanceof MarkupOutputFormat
? (MarkupOutputFormat>) outputFormat : null;
NumericalOutput result;
if (fmt != null) {
int minFrac = -1; // -1 indicates that the value has not been set
int maxFrac = -1;
StringTokenizer st = new StringTokenizer(fmt.image, "mM", true);
char type = '-';
while (st.hasMoreTokens()) {
String token = st.nextToken();
try {
if (type != '-') {
switch (type) {
case 'm':
if (minFrac != -1) {if (true) throw new ParseException("Invalid formatting string", template, fmt);}
minFrac = Integer.parseInt(token);
break;
case 'M':
if (maxFrac != -1) {if (true) throw new ParseException("Invalid formatting string", template, fmt);}
maxFrac = Integer.parseInt(token);
break;
default:
{if (true) throw new ParseException("Invalid formatting string", template, fmt);}
}
type = '-';
} else if (token.equals("m")) {
type = 'm';
} else if (token.equals("M")) {
type = 'M';
} else {
{if (true) throw new ParseException();}
}
} catch (ParseException e) {
{if (true) throw new ParseException("Invalid format specifier " + fmt.image, template, fmt);}
} catch (NumberFormatException e) {
{if (true) throw new ParseException("Invalid number in the format specifier " + fmt.image, template, fmt);}
}
}
if (maxFrac == -1) {
if (minFrac == -1) {
{if (true) throw new ParseException(
"Invalid format specification, at least one of m and M must be specified!", template, fmt);}
}
maxFrac = minFrac;
} else if (minFrac == -1) {
minFrac = 0;
}
if (minFrac > maxFrac) {
{if (true) throw new ParseException(
"Invalid format specification, min cannot be greater than max!", template, fmt);}
}
if (minFrac > 50 || maxFrac > 50) {// sanity check
{if (true) throw new ParseException("Cannot specify more than 50 fraction digits", template, fmt);}
}
result = new NumericalOutput(exp, minFrac, maxFrac, autoEscOF);
} else { // if format != null
result = new NumericalOutput(exp, autoEscOF);
}
result.setLocation(template, begin, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement If() throws ParseException {Token start, end, t;
Expression condition;
TemplateElements children;
IfBlock ifBlock;
ConditionalBlock cblock;
start = jj_consume_token(IF);
condition = Expression();
end = jj_consume_token(DIRECTIVE_END);
children = MixedContentElements();
cblock = new ConditionalBlock(condition, children, ConditionalBlock.TYPE_IF);
cblock.setLocation(template, start, end, children);
ifBlock = new IfBlock(cblock);
label_8:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ELSE_IF:{
;
break;
}
default:
jj_la1[24] = jj_gen;
break label_8;
}
t = jj_consume_token(ELSE_IF);
condition = Expression();
end = LooseDirectiveEnd();
children = MixedContentElements();
cblock = new ConditionalBlock(condition, children, ConditionalBlock.TYPE_ELSE_IF);
cblock.setLocation(template, t, end, children);
ifBlock.addBlock(cblock);
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ELSE:{
t = jj_consume_token(ELSE);
children = MixedContentElements();
cblock = new ConditionalBlock(null, children, ConditionalBlock.TYPE_ELSE);
cblock.setLocation(template, t, t, children);
ifBlock.addBlock(cblock);
break;
}
default:
jj_la1[25] = jj_gen;
;
}
end = jj_consume_token(END_IF);
ifBlock.setLocation(template, start, end);
{if ("" != null) return ifBlock;}
throw new Error("Missing return statement in function");
}
final public AttemptBlock Attempt() throws ParseException {Token start, end;
TemplateElements children;
RecoveryBlock recoveryBlock;
start = jj_consume_token(ATTEMPT);
children = MixedContentElements();
recoveryBlock = Recover();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case END_RECOVER:{
end = jj_consume_token(END_RECOVER);
break;
}
case END_ATTEMPT:{
end = jj_consume_token(END_ATTEMPT);
break;
}
default:
jj_la1[26] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
AttemptBlock result = new AttemptBlock(children, recoveryBlock);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public RecoveryBlock Recover() throws ParseException {Token start;
TemplateElements children;
start = jj_consume_token(RECOVER);
children = MixedContentElements();
RecoveryBlock result = new RecoveryBlock(children);
result.setLocation(template, start, start, children);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement List() throws ParseException {Expression exp;
Token loopVar = null, loopVar2 = null, start, end;
TemplateElements childrendBeforeElse;
ElseOfList elseOfList = null;
ParserIteratorBlockContext iterCtx;
start = jj_consume_token(LIST);
exp = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case AS:{
jj_consume_token(AS);
loopVar = jj_consume_token(ID);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
loopVar2 = jj_consume_token(ID);
break;
}
default:
jj_la1[27] = jj_gen;
;
}
break;
}
default:
jj_la1[28] = jj_gen;
;
}
jj_consume_token(DIRECTIVE_END);
iterCtx = pushIteratorBlockContext();
if (loopVar != null) {
iterCtx.loopVarName = loopVar.image;
breakableDirectiveNesting++;
continuableDirectiveNesting++;
if (loopVar2 != null) {
iterCtx.loopVar2Name = loopVar2.image;
iterCtx.hashListing = true;
if (iterCtx.loopVar2Name.equals(iterCtx.loopVarName)) {
{if (true) throw new ParseException(
"The key and value loop variable names must differ, but both were: " + iterCtx.loopVarName,
template, start);}
}
}
}
childrendBeforeElse = MixedContentElements();
if (loopVar != null) {
breakableDirectiveNesting--;
continuableDirectiveNesting--;
} else if (iterCtx.kind != ITERATOR_BLOCK_KIND_ITEMS) {
{if (true) throw new ParseException(
"#list must have either \"as loopVar\" parameter or nested #items that belongs to it.",
template, start);}
}
popIteratorBlockContext();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ELSE:{
elseOfList = ElseOfList();
break;
}
default:
jj_la1[29] = jj_gen;
;
}
end = jj_consume_token(END_LIST);
IteratorBlock list = new IteratorBlock(
exp,
loopVar != null ? loopVar.image : null, // null when we have a nested #items
loopVar2 != null ? loopVar2.image : null,
childrendBeforeElse, iterCtx.hashListing, false);
list.setLocation(template, start, end);
TemplateElement result;
if (elseOfList == null) {
result = list;
} else {
result = new ListElseContainer(list, elseOfList);
result.setLocation(template, start, end);
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public ElseOfList ElseOfList() throws ParseException {Token start;
TemplateElements children;
start = jj_consume_token(ELSE);
children = MixedContentElements();
ElseOfList result = new ElseOfList(children);
result.setLocation(template, start, start, children);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public IteratorBlock ForEach() throws ParseException {Expression exp;
Token loopVar, start, end;
TemplateElements children;
start = jj_consume_token(FOREACH);
loopVar = jj_consume_token(ID);
jj_consume_token(IN);
exp = Expression();
jj_consume_token(DIRECTIVE_END);
ParserIteratorBlockContext iterCtx = pushIteratorBlockContext();
iterCtx.loopVarName = loopVar.image;
iterCtx.kind = ITERATOR_BLOCK_KIND_FOREACH;
breakableDirectiveNesting++;
continuableDirectiveNesting++;
children = MixedContentElements();
end = jj_consume_token(END_FOREACH);
breakableDirectiveNesting--;
continuableDirectiveNesting--;
popIteratorBlockContext();
IteratorBlock result = new IteratorBlock(exp, loopVar.image, null, children, false, true);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Items Items() throws ParseException {Token loopVar, loopVar2 = null, start, end;
TemplateElements children;
ParserIteratorBlockContext iterCtx;
start = jj_consume_token(ITEMS);
loopVar = jj_consume_token(ID);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
loopVar2 = jj_consume_token(ID);
break;
}
default:
jj_la1[30] = jj_gen;
;
}
jj_consume_token(DIRECTIVE_END);
iterCtx = peekIteratorBlockContext();
if (iterCtx == null) {
{if (true) throw new ParseException("#items must be inside a #list block.", template, start);}
}
if (iterCtx.loopVarName != null) {
String msg;
if (iterCtx.kind == ITERATOR_BLOCK_KIND_FOREACH) {
msg = forEachDirectiveSymbol() + " doesn't support nested #items.";
} else if (iterCtx.kind == ITERATOR_BLOCK_KIND_ITEMS) {
msg = "Can't nest #items into each other when they belong to the same #list.";
} else {
msg = "The parent #list of the #items must not have \"as loopVar\" parameter.";
}
{if (true) throw new ParseException(msg, template, start);}
}
iterCtx.kind = ITERATOR_BLOCK_KIND_ITEMS;
iterCtx.loopVarName = loopVar.image;
if (loopVar2 != null) {
iterCtx.loopVar2Name = loopVar2.image;
iterCtx.hashListing = true;
if (iterCtx.loopVar2Name.equals(iterCtx.loopVarName)) {
{if (true) throw new ParseException(
"The key and value loop variable names must differ, but both were: " + iterCtx.loopVarName,
template, start);}
}
}
breakableDirectiveNesting++;
continuableDirectiveNesting++;
children = MixedContentElements();
end = jj_consume_token(END_ITEMS);
breakableDirectiveNesting--;
continuableDirectiveNesting--;
iterCtx.loopVarName = null;
iterCtx.loopVar2Name = null;
Items result = new Items(loopVar.image, loopVar2 != null ? loopVar2.image : null, children);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Sep Sep() throws ParseException {Token loopVar, start, end = null;
TemplateElements children;
start = jj_consume_token(SEP);
if (peekIteratorBlockContext() == null) {
{if (true) throw new ParseException(
"#sep must be inside a #list (or " + forEachDirectiveSymbol() + ") block.",
template, start);}
}
children = MixedContentElements();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case END_SEP:{
end = jj_consume_token(END_SEP);
break;
}
default:
jj_la1[31] = jj_gen;
;
}
Sep result = new Sep(children);
if (end != null) {
result.setLocation(template, start, end);
} else {
result.setLocation(template, start, start, children);
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public VisitNode Visit() throws ParseException {Token start, end;
Expression targetNode, namespaces = null;
start = jj_consume_token(VISIT);
targetNode = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case USING:{
jj_consume_token(USING);
namespaces = Expression();
break;
}
default:
jj_la1[32] = jj_gen;
;
}
end = LooseDirectiveEnd();
VisitNode result = new VisitNode(targetNode, namespaces);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public RecurseNode Recurse() throws ParseException {Token start, end = null;
Expression node = null, namespaces = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SIMPLE_RECURSE:{
start = jj_consume_token(SIMPLE_RECURSE);
break;
}
case RECURSE:{
start = jj_consume_token(RECURSE);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STRING_LITERAL:
case RAW_STRING:
case FALSE:
case TRUE:
case INTEGER:
case DECIMAL:
case DOT:
case PLUS:
case MINUS:
case EXCLAM:
case OPEN_BRACKET:
case OPEN_PAREN:
case OPENING_CURLY_BRACKET:
case ID:{
node = Expression();
break;
}
default:
jj_la1[33] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case USING:{
jj_consume_token(USING);
namespaces = Expression();
break;
}
default:
jj_la1[34] = jj_gen;
;
}
end = LooseDirectiveEnd();
break;
}
default:
jj_la1[35] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (end == null) end = start;
RecurseNode result = new RecurseNode(node, namespaces);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public FallbackInstruction FallBack() throws ParseException {Token tok;
tok = jj_consume_token(FALLBACK);
if (!inMacro) {
{if (true) throw new ParseException("Cannot fall back outside a macro.", template, tok);}
}
FallbackInstruction result = new FallbackInstruction();
result.setLocation(template, tok, tok);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production used to break out of a loop or a switch block.
*/
final public BreakInstruction Break() throws ParseException {Token start;
start = jj_consume_token(BREAK);
if (breakableDirectiveNesting < 1) {
{if (true) throw new ParseException(start.image + " must be nested inside a directive that supports it: "
+ " #list with \"as\", #items, #switch (or the deprecated " + forEachDirectiveSymbol() + ")",
template, start);}
}
BreakInstruction result = new BreakInstruction();
result.setLocation(template, start, start);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production used to skip an iteration in a loop.
*/
final public ContinueInstruction Continue() throws ParseException {Token start;
start = jj_consume_token(CONTINUE);
if (continuableDirectiveNesting < 1) {
{if (true) throw new ParseException(start.image + " must be nested inside a directive that supports it: "
+ " #list with \"as\", #items (or the deprecated " + forEachDirectiveSymbol() + ")",
template, start);}
}
ContinueInstruction result = new ContinueInstruction();
result.setLocation(template, start, start);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production used to jump out of a macro.
* The stop instruction terminates the rendering of the template.
*/
final public ReturnInstruction Return() throws ParseException {Token start, end = null;
Expression exp = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SIMPLE_RETURN:{
start = jj_consume_token(SIMPLE_RETURN);
end = start;
break;
}
case RETURN:{
start = jj_consume_token(RETURN);
exp = Expression();
end = LooseDirectiveEnd();
break;
}
default:
jj_la1[36] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (inMacro) {
if (exp != null) {
{if (true) throw new ParseException("A macro cannot return a value", template, start);}
}
} else if (inFunction) {
if (exp == null) {
{if (true) throw new ParseException("A function must return a value", template, start);}
}
} else {
if (exp == null) {
{if (true) throw new ParseException(
"A return instruction can only occur inside a macro or function", template, start);}
}
}
ReturnInstruction result = new ReturnInstruction(exp);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public StopInstruction Stop() throws ParseException {Token start = null;
Expression exp = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case HALT:{
start = jj_consume_token(HALT);
break;
}
case STOP:{
start = jj_consume_token(STOP);
exp = Expression();
LooseDirectiveEnd();
break;
}
default:
jj_la1[37] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
StopInstruction result = new StopInstruction(exp);
result.setLocation(template, start, start);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement Nested() throws ParseException {Token t, end;
ArrayList bodyParameters;
BodyInstruction result = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SIMPLE_NESTED:{
t = jj_consume_token(SIMPLE_NESTED);
result = new BodyInstruction(null);
result.setLocation(template, t, t);
break;
}
case NESTED:{
t = jj_consume_token(NESTED);
bodyParameters = PositionalArgs();
end = LooseDirectiveEnd();
result = new BodyInstruction(bodyParameters);
result.setLocation(template, t, end);
break;
}
default:
jj_la1[38] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (!inMacro) {
{if (true) throw new ParseException("Cannot use a " + t.image + " instruction outside a macro.", template, t);}
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement Flush() throws ParseException {Token t;
t = jj_consume_token(FLUSH);
FlushInstruction result = new FlushInstruction();
result.setLocation(template, t, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement Trim() throws ParseException {Token t;
TrimInstruction result = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TRIM:{
t = jj_consume_token(TRIM);
result = new TrimInstruction(true, true);
break;
}
case LTRIM:{
t = jj_consume_token(LTRIM);
result = new TrimInstruction(true, false);
break;
}
case RTRIM:{
t = jj_consume_token(RTRIM);
result = new TrimInstruction(false, true);
break;
}
case NOTRIM:{
t = jj_consume_token(NOTRIM);
result = new TrimInstruction(false, false);
break;
}
default:
jj_la1[39] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
result.setLocation(template, t, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement Assign() throws ParseException {Token start, end;
int scope;
Token id = null;
Token equalsOp;
Expression nameExp, exp, nsExp = null;
String varName;
ArrayList assignments = new ArrayList();
Assignment ass;
TemplateElements children;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ASSIGN:{
start = jj_consume_token(ASSIGN);
scope = Assignment.NAMESPACE;
break;
}
case GLOBALASSIGN:{
start = jj_consume_token(GLOBALASSIGN);
scope = Assignment.GLOBAL;
break;
}
case LOCALASSIGN:{
start = jj_consume_token(LOCALASSIGN);
scope = Assignment.LOCAL;
scope = Assignment.LOCAL;
if (!inMacro && !inFunction) {
{if (true) throw new ParseException("Local variable assigned outside a macro.", template, start);}
}
break;
}
default:
jj_la1[40] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
nameExp = IdentifierOrStringLiteral();
varName = (nameExp instanceof StringLiteral)
? ((StringLiteral) nameExp).getAsString()
: ((Identifier) nameExp).getName();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:
case PLUS_EQUALS:
case MINUS_EQUALS:
case TIMES_EQUALS:
case DIV_EQUALS:
case MOD_EQUALS:
case PLUS_PLUS:
case MINUS_MINUS:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:
case PLUS_EQUALS:
case MINUS_EQUALS:
case TIMES_EQUALS:
case DIV_EQUALS:
case MOD_EQUALS:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:{
jj_consume_token(EQUALS);
break;
}
case PLUS_EQUALS:{
jj_consume_token(PLUS_EQUALS);
break;
}
case MINUS_EQUALS:{
jj_consume_token(MINUS_EQUALS);
break;
}
case TIMES_EQUALS:{
jj_consume_token(TIMES_EQUALS);
break;
}
case DIV_EQUALS:{
jj_consume_token(DIV_EQUALS);
break;
}
case MOD_EQUALS:{
jj_consume_token(MOD_EQUALS);
break;
}
default:
jj_la1[41] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
equalsOp = token;
exp = Expression();
break;
}
case PLUS_PLUS:
case MINUS_MINUS:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case PLUS_PLUS:{
jj_consume_token(PLUS_PLUS);
break;
}
case MINUS_MINUS:{
jj_consume_token(MINUS_MINUS);
break;
}
default:
jj_la1[42] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
equalsOp = token;
exp = null;
break;
}
default:
jj_la1[43] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
ass = new Assignment(varName, equalsOp.kind, exp, scope);
if (exp != null) {
ass.setLocation(template, nameExp, exp);
} else {
ass.setLocation(template, nameExp, equalsOp);
}
assignments.add(ass);
label_9:
while (true) {
if (jj_2_10(2147483647)) {
;
} else {
break label_9;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
default:
jj_la1[44] = jj_gen;
;
}
nameExp = IdentifierOrStringLiteral();
varName = (nameExp instanceof StringLiteral)
? ((StringLiteral) nameExp).getAsString()
: ((Identifier) nameExp).getName();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:
case PLUS_EQUALS:
case MINUS_EQUALS:
case TIMES_EQUALS:
case DIV_EQUALS:
case MOD_EQUALS:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:{
jj_consume_token(EQUALS);
break;
}
case PLUS_EQUALS:{
jj_consume_token(PLUS_EQUALS);
break;
}
case MINUS_EQUALS:{
jj_consume_token(MINUS_EQUALS);
break;
}
case TIMES_EQUALS:{
jj_consume_token(TIMES_EQUALS);
break;
}
case DIV_EQUALS:{
jj_consume_token(DIV_EQUALS);
break;
}
case MOD_EQUALS:{
jj_consume_token(MOD_EQUALS);
break;
}
default:
jj_la1[45] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
equalsOp = token;
exp = Expression();
break;
}
case PLUS_PLUS:
case MINUS_MINUS:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case PLUS_PLUS:{
jj_consume_token(PLUS_PLUS);
break;
}
case MINUS_MINUS:{
jj_consume_token(MINUS_MINUS);
break;
}
default:
jj_la1[46] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
equalsOp = token;
exp = null;
break;
}
default:
jj_la1[47] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
ass = new Assignment(varName, equalsOp.kind, exp, scope);
if (exp != null) {
ass.setLocation(template, nameExp, exp);
} else {
ass.setLocation(template, nameExp, equalsOp);
}
assignments.add(ass);
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case IN:{
id = jj_consume_token(IN);
nsExp = Expression();
if (scope != Assignment.NAMESPACE) {
{if (true) throw new ParseException("Cannot assign to namespace here.", template, id);}
}
break;
}
default:
jj_la1[48] = jj_gen;
;
}
end = LooseDirectiveEnd();
if (assignments.size() == 1) {
Assignment a = (Assignment) assignments.get(0);
a.setNamespaceExp(nsExp);
a.setLocation(template, start, end);
{if ("" != null) return a;}
} else {
AssignmentInstruction ai = new AssignmentInstruction(scope);
for (int i = 0; i< assignments.size(); i++) {
ai.addAssignment((Assignment) assignments.get(i));
}
ai.setNamespaceExp(nsExp);
ai.setLocation(template, start, end);
{if ("" != null) return ai;}
}
break;
}
case IN:
case DIRECTIVE_END:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case IN:{
id = jj_consume_token(IN);
nsExp = Expression();
if (scope != Assignment.NAMESPACE) {
{if (true) throw new ParseException("Cannot assign to namespace here.", template, id);}
}
break;
}
default:
jj_la1[49] = jj_gen;
;
}
jj_consume_token(DIRECTIVE_END);
children = MixedContentElements();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case END_LOCAL:{
end = jj_consume_token(END_LOCAL);
if (scope != Assignment.LOCAL) {
{if (true) throw new ParseException("Mismatched assignment tags.", template, end);}
}
break;
}
case END_ASSIGN:{
end = jj_consume_token(END_ASSIGN);
if (scope != Assignment.NAMESPACE) {
{if (true) throw new ParseException("Mismatched assignment tags.", template, end);}
}
break;
}
case END_GLOBAL:{
end = jj_consume_token(END_GLOBAL);
if (scope != Assignment.GLOBAL) {if (true) throw new ParseException(
"Mismatched assignment tags", template, end);}
break;
}
default:
jj_la1[50] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
BlockAssignment ba = new BlockAssignment(
children, varName, scope, nsExp,
getMarkupOutputFormat());
ba.setLocation(template, start, end);
{if ("" != null) return ba;}
break;
}
default:
jj_la1[51] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
throw new Error("Missing return statement in function");
}
final public Include Include() throws ParseException {Expression nameExp;
Token att, start, end;
Expression exp, parseExp = null, encodingExp = null, ignoreMissingExp = null;
start = jj_consume_token(_INCLUDE);
nameExp = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SEMICOLON:{
jj_consume_token(SEMICOLON);
break;
}
default:
jj_la1[52] = jj_gen;
;
}
label_10:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[53] = jj_gen;
break label_10;
}
att = jj_consume_token(ID);
jj_consume_token(EQUALS);
exp = Expression();
String attString = att.image;
if (attString.equalsIgnoreCase("parse")) {
parseExp = exp;
} else if (attString.equalsIgnoreCase("encoding")) {
encodingExp = exp;
} else if (attString.equalsIgnoreCase("ignore_missing") || attString.equals("ignoreMissing")) {
token_source.checkNamingConvention(att);
ignoreMissingExp = exp;
} else {
String correctedName = attString.equals("ignoreMissing") ? "ignore_missing" : null;
{if (true) throw new ParseException(
"Unsupported named #include parameter: \"" + attString + "\". Supported parameters are: "
+ "\"parse\", \"encoding\", \"ignore_missing\"."
+ (correctedName == null
? ""
: " Supporting camelCase parameter names is planned for FreeMarker 2.4.0; "
+ "check if an update is available, and if it indeed supports camel "
+ "case."),
template, att);}
}
}
end = LooseDirectiveEnd();
Include result = new Include(template, nameExp, encodingExp, parseExp, ignoreMissingExp);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public LibraryLoad Import() throws ParseException {Token start, end, ns;
Expression nameExp;
start = jj_consume_token(IMPORT);
nameExp = Expression();
jj_consume_token(AS);
ns = jj_consume_token(ID);
end = LooseDirectiveEnd();
LibraryLoad result = new LibraryLoad(template, nameExp, ns.image);
result.setLocation(template, start, end);
template.addImport(result);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Macro Macro() throws ParseException {Token arg, start, end;
Expression nameExp;
String name;
ArrayList argNames = new ArrayList();
HashMap args = new HashMap();
ArrayList defNames = new ArrayList();
Expression defValue = null;
List lastIteratorBlockContexts;
int lastBreakableDirectiveNesting;
int lastContiunableDirectiveNesting;
TemplateElements children;
boolean isFunction = false, hasDefaults = false;
boolean isCatchAll = false;
String catchAll = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case MACRO:{
start = jj_consume_token(MACRO);
break;
}
case FUNCTION:{
start = jj_consume_token(FUNCTION);
isFunction = true;
break;
}
default:
jj_la1[54] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (inMacro || inFunction) {
{if (true) throw new ParseException("Macro or function definitions can't be nested into each other.", template, start);}
}
if (isFunction) inFunction = true; else inMacro = true;
nameExp = IdentifierOrStringLiteral();
name = (nameExp instanceof StringLiteral)
? ((StringLiteral) nameExp).getAsString()
: ((Identifier) nameExp).getName();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case OPEN_PAREN:{
jj_consume_token(OPEN_PAREN);
break;
}
default:
jj_la1[55] = jj_gen;
;
}
label_11:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[56] = jj_gen;
break label_11;
}
arg = jj_consume_token(ID);
defValue = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ELLIPSIS:{
jj_consume_token(ELLIPSIS);
isCatchAll = true;
break;
}
default:
jj_la1[57] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EQUALS:{
jj_consume_token(EQUALS);
defValue = Expression();
defNames.add(arg.image);
hasDefaults = true;
break;
}
default:
jj_la1[58] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
default:
jj_la1[59] = jj_gen;
;
}
if (catchAll != null) {
{if (true) throw new ParseException(
"There may only be one \"catch-all\" parameter in a macro declaration, and it must be the last parameter.",
template, arg);}
}
if (isCatchAll) {
if (defValue != null) {
{if (true) throw new ParseException(
"\"Catch-all\" macro parameter may not have a default value.",
template, arg);}
}
catchAll = arg.image;
} else {
argNames.add(arg.image);
if (hasDefaults && defValue == null) {
{if (true) throw new ParseException(
"In a macro declaration, parameters without a default value "
+ "must all occur before the parameters with default values.",
template, arg);}
}
args.put(arg.image, defValue);
}
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case CLOSE_PAREN:{
jj_consume_token(CLOSE_PAREN);
break;
}
default:
jj_la1[60] = jj_gen;
;
}
jj_consume_token(DIRECTIVE_END);
// To prevent parser check loopholes like <#list ...><#macro ...><#break>#macro>#list>.
lastIteratorBlockContexts = iteratorBlockContexts;
iteratorBlockContexts = null;
if (incompatibleImprovements >= _TemplateAPI.VERSION_INT_2_3_23) {
lastBreakableDirectiveNesting = breakableDirectiveNesting;
lastContiunableDirectiveNesting = continuableDirectiveNesting;
breakableDirectiveNesting = 0;
continuableDirectiveNesting = 0;
} else {
lastBreakableDirectiveNesting = 0; // Just to prevent uninitialized local variable error later
lastContiunableDirectiveNesting = 0;
}
children = MixedContentElements();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case END_MACRO:{
end = jj_consume_token(END_MACRO);
if (isFunction) {if (true) throw new ParseException("Expected function end tag here.", template, end);}
break;
}
case END_FUNCTION:{
end = jj_consume_token(END_FUNCTION);
if (!isFunction) {if (true) throw new ParseException("Expected macro end tag here.", template, end);}
break;
}
default:
jj_la1[61] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
iteratorBlockContexts = lastIteratorBlockContexts;
if (incompatibleImprovements >= _TemplateAPI.VERSION_INT_2_3_23) {
breakableDirectiveNesting = lastBreakableDirectiveNesting;
continuableDirectiveNesting = lastContiunableDirectiveNesting;
}
inMacro = inFunction = false;
Macro result = new Macro(name, argNames, args, catchAll, isFunction, children);
result.setLocation(template, start, end);
template.addMacro(result);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public CompressedBlock Compress() throws ParseException {TemplateElements children;
Token start, end;
start = jj_consume_token(COMPRESS);
children = MixedContentElements();
end = jj_consume_token(END_COMPRESS);
CompressedBlock cb = new CompressedBlock(children);
cb.setLocation(template, start, end);
{if ("" != null) return cb;}
throw new Error("Missing return statement in function");
}
final public TemplateElement UnifiedMacroTransform() throws ParseException {Token start = null, end, t;
HashMap namedArgs = null;
ArrayList positionalArgs = null, bodyParameters = null;
Expression startTagNameExp;
TemplateElements children;
Expression exp;
int pushedCtxCount = 0;
start = jj_consume_token(UNIFIED_CALL);
exp = Expression();
if (exp instanceof Identifier || (exp instanceof Dot && ((Dot) exp).onlyHasIdentifiers())) {
startTagNameExp = exp;
} else {
startTagNameExp = null;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERMINATING_WHITESPACE:{
jj_consume_token(TERMINATING_WHITESPACE);
break;
}
default:
jj_la1[62] = jj_gen;
;
}
if (jj_2_11(2147483647)) {
namedArgs = NamedArgs();
} else {
positionalArgs = PositionalArgs();
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SEMICOLON:{
jj_consume_token(SEMICOLON);
bodyParameters = new ArrayList(4);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:
case TERMINATING_WHITESPACE:{
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERMINATING_WHITESPACE:{
jj_consume_token(TERMINATING_WHITESPACE);
break;
}
default:
jj_la1[63] = jj_gen;
;
}
t = jj_consume_token(ID);
bodyParameters.add(t.image);
label_12:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:
case TERMINATING_WHITESPACE:{
;
break;
}
default:
jj_la1[64] = jj_gen;
break label_12;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERMINATING_WHITESPACE:{
jj_consume_token(TERMINATING_WHITESPACE);
break;
}
default:
jj_la1[65] = jj_gen;
;
}
jj_consume_token(COMMA);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERMINATING_WHITESPACE:{
jj_consume_token(TERMINATING_WHITESPACE);
break;
}
default:
jj_la1[66] = jj_gen;
;
}
t = jj_consume_token(ID);
bodyParameters.add(t.image);
}
break;
}
default:
jj_la1[67] = jj_gen;
;
}
break;
}
default:
jj_la1[68] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EMPTY_DIRECTIVE_END:{
end = jj_consume_token(EMPTY_DIRECTIVE_END);
children = TemplateElements.EMPTY;
break;
}
case DIRECTIVE_END:{
jj_consume_token(DIRECTIVE_END);
if (bodyParameters != null && iteratorBlockContexts != null && !iteratorBlockContexts.isEmpty()) {
// It's possible that we shadow a #list/#items loop variable, in which case that must be noted.
int ctxsLen = iteratorBlockContexts.size();
int bodyParsLen = bodyParameters.size();
for (int bodyParIdx = 0; bodyParIdx < bodyParsLen; bodyParIdx++) {
String bodyParName = (String) bodyParameters.get(bodyParIdx);
walkCtxSack: for (int ctxIdx = ctxsLen - 1; ctxIdx >= 0; ctxIdx--) {
ParserIteratorBlockContext ctx
= (ParserIteratorBlockContext) iteratorBlockContexts.get(ctxIdx);
if (ctx.loopVarName != null && ctx.loopVarName.equals(bodyParName)) {
// If it wasn't already shadowed, shadow it:
if (ctx.kind != ITERATOR_BLOCK_KIND_USER_DIRECTIVE) {
ParserIteratorBlockContext shadowingCtx = pushIteratorBlockContext();
shadowingCtx.loopVarName = bodyParName;
shadowingCtx.kind = ITERATOR_BLOCK_KIND_USER_DIRECTIVE;
pushedCtxCount++;
}
break walkCtxSack;
}
}
}
}
children = MixedContentElements();
end = jj_consume_token(UNIFIED_CALL_END);
for (int i = 0; i < pushedCtxCount; i++) {
popIteratorBlockContext();
}
String endTagName = end.image.substring(3, end.image.length() - 1).trim();
if (endTagName.length() > 0) {
if (startTagNameExp == null) {
{if (true) throw new ParseException("Expecting @>", template, end);}
} else {
String startTagName = startTagNameExp.getCanonicalForm();
if (!endTagName.equals(startTagName)) {
{if (true) throw new ParseException("Expecting @> or @" + startTagName + ">", template, end);}
}
}
}
break;
}
default:
jj_la1[69] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
TemplateElement result = (positionalArgs != null)
? new UnifiedCall(exp, positionalArgs, children, bodyParameters)
: new UnifiedCall(exp, namedArgs, children, bodyParameters);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TemplateElement Call() throws ParseException {Token start, end, id;
HashMap namedArgs = null;
ArrayList positionalArgs = null;
Identifier macroName= null;
start = jj_consume_token(CALL);
id = jj_consume_token(ID);
macroName = new Identifier(id.image);
macroName.setLocation(template, id, id);
if (jj_2_13(2147483647)) {
namedArgs = NamedArgs();
} else {
if (jj_2_12(2147483647)) {
jj_consume_token(OPEN_PAREN);
} else {
;
}
positionalArgs = PositionalArgs();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case CLOSE_PAREN:{
jj_consume_token(CLOSE_PAREN);
break;
}
default:
jj_la1[70] = jj_gen;
;
}
}
end = LooseDirectiveEnd();
UnifiedCall result = null;
if (positionalArgs != null) {
result = new UnifiedCall(macroName, positionalArgs, TemplateElements.EMPTY, null);
} else {
result = new UnifiedCall(macroName, namedArgs, TemplateElements.EMPTY, null);
}
result.legacySyntax = true;
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public HashMap NamedArgs() throws ParseException {HashMap result = new HashMap();
Token t;
Expression exp;
label_13:
while (true) {
t = jj_consume_token(ID);
jj_consume_token(EQUALS);
token_source.SwitchTo(token_source.NAMED_PARAMETER_EXPRESSION);
token_source.inInvocation = true;
exp = Expression();
result.put(t.image, exp);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[71] = jj_gen;
break label_13;
}
}
token_source.inInvocation = false;
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public ArrayList PositionalArgs() throws ParseException {ArrayList result = new ArrayList();
Expression arg;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STRING_LITERAL:
case RAW_STRING:
case FALSE:
case TRUE:
case INTEGER:
case DECIMAL:
case DOT:
case PLUS:
case MINUS:
case EXCLAM:
case OPEN_BRACKET:
case OPEN_PAREN:
case OPENING_CURLY_BRACKET:
case ID:{
arg = Expression();
result.add(arg);
label_14:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STRING_LITERAL:
case RAW_STRING:
case FALSE:
case TRUE:
case INTEGER:
case DECIMAL:
case DOT:
case PLUS:
case MINUS:
case EXCLAM:
case COMMA:
case OPEN_BRACKET:
case OPEN_PAREN:
case OPENING_CURLY_BRACKET:
case ID:{
;
break;
}
default:
jj_la1[72] = jj_gen;
break label_14;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
default:
jj_la1[73] = jj_gen;
;
}
arg = Expression();
result.add(arg);
}
break;
}
default:
jj_la1[74] = jj_gen;
;
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public Comment Comment() throws ParseException {Token start, end;
StringBuilder buf = new StringBuilder();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMENT:{
start = jj_consume_token(COMMENT);
break;
}
case TERSE_COMMENT:{
start = jj_consume_token(TERSE_COMMENT);
break;
}
default:
jj_la1[75] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
end = UnparsedContent(start, buf);
Comment result = new Comment(buf.toString());
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TextBlock NoParse() throws ParseException {Token start, end;
StringBuilder buf = new StringBuilder();
start = jj_consume_token(NOPARSE);
end = UnparsedContent(start, buf);
TextBlock result = new TextBlock(buf.toString(), true);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TransformBlock Transform() throws ParseException {Token start, end, argName;
Expression exp, argExp;
TemplateElements children = null;
HashMap args = null;
start = jj_consume_token(TRANSFORM);
exp = Expression();
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case SEMICOLON:{
jj_consume_token(SEMICOLON);
break;
}
default:
jj_la1[76] = jj_gen;
;
}
label_15:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[77] = jj_gen;
break label_15;
}
argName = jj_consume_token(ID);
jj_consume_token(EQUALS);
argExp = Expression();
if (args == null) args = new HashMap();
args.put(argName.image, argExp);
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case EMPTY_DIRECTIVE_END:{
end = jj_consume_token(EMPTY_DIRECTIVE_END);
break;
}
case DIRECTIVE_END:{
jj_consume_token(DIRECTIVE_END);
children = MixedContentElements();
end = jj_consume_token(END_TRANSFORM);
break;
}
default:
jj_la1[78] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
TransformBlock result = new TransformBlock(exp, args, children);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public SwitchBlock Switch() throws ParseException {SwitchBlock switchBlock;
MixedContent ignoredSectionBeforeFirstCase = null;
Case caseIns;
Expression switchExp;
Token start, end;
boolean defaultFound = false;
start = jj_consume_token(SWITCH);
switchExp = Expression();
jj_consume_token(DIRECTIVE_END);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMENT:
case TERSE_COMMENT:
case STATIC_TEXT_WS:{
ignoredSectionBeforeFirstCase = WhitespaceAndComments();
break;
}
default:
jj_la1[79] = jj_gen;
;
}
breakableDirectiveNesting++;
switchBlock = new SwitchBlock(switchExp, ignoredSectionBeforeFirstCase);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case CASE:
case DEFAUL:{
label_16:
while (true) {
caseIns = Case();
if (caseIns.condition == null) {
if (defaultFound) {
{if (true) throw new ParseException(
"You can only have one default case in a switch statement", template, start);}
}
defaultFound = true;
}
switchBlock.addCase(caseIns);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case CASE:
case DEFAUL:{
;
break;
}
default:
jj_la1[80] = jj_gen;
break label_16;
}
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:{
jj_consume_token(STATIC_TEXT_WS);
break;
}
default:
jj_la1[81] = jj_gen;
;
}
break;
}
default:
jj_la1[82] = jj_gen;
;
}
end = jj_consume_token(END_SWITCH);
breakableDirectiveNesting--;
switchBlock.setLocation(template, start, end);
{if ("" != null) return switchBlock;}
throw new Error("Missing return statement in function");
}
final public Case Case() throws ParseException {Expression exp;
TemplateElements children;
Token start;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case CASE:{
start = jj_consume_token(CASE);
exp = Expression();
jj_consume_token(DIRECTIVE_END);
break;
}
case DEFAUL:{
start = jj_consume_token(DEFAUL);
exp = null;
break;
}
default:
jj_la1[83] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
children = MixedContentElements();
Case result = new Case(exp, children);
result.setLocation(template, start, start, children);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public EscapeBlock Escape() throws ParseException {Token variable, start, end;
Expression escapeExpr;
TemplateElements children;
start = jj_consume_token(ESCAPE);
if (outputFormat instanceof MarkupOutputFormat && autoEscaping) {
{if (true) throw new ParseException(
"Using the \"escape\" directive (legacy escaping) is not allowed when auto-escaping is on with "
+ "a markup output format (" + outputFormat.getName()
+ "), to avoid confusion and double-escaping mistakes.",
template, start);}
}
variable = jj_consume_token(ID);
jj_consume_token(AS);
escapeExpr = Expression();
jj_consume_token(DIRECTIVE_END);
EscapeBlock result = new EscapeBlock(variable.image, escapeExpr, escapedExpression(escapeExpr));
escapes.addFirst(result);
children = MixedContentElements();
result.setContent(children);
escapes.removeFirst();
end = jj_consume_token(END_ESCAPE);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public NoEscapeBlock NoEscape() throws ParseException {Token start, end;
TemplateElements children;
start = jj_consume_token(NOESCAPE);
if (escapes.isEmpty()) {
{if (true) throw new ParseException("#noescape with no matching #escape encountered.", template, start);}
}
Object escape = escapes.removeFirst();
children = MixedContentElements();
end = jj_consume_token(END_NOESCAPE);
escapes.addFirst(escape);
NoEscapeBlock result = new NoEscapeBlock(children);
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public OutputFormatBlock OutputFormat() throws ParseException {Token start, end;
Expression paramExp;
TemplateElements children;
OutputFormat lastOutputFormat;
start = jj_consume_token(OUTPUTFORMAT);
paramExp = Expression();
jj_consume_token(DIRECTIVE_END);
if (!paramExp.isLiteral()) {
{if (true) throw new ParseException(
"Parameter expression must be parse-time evaluable (constant): "
+ paramExp.getCanonicalForm(),
paramExp);}
}
TemplateModel paramTM;
try {
paramTM = paramExp.eval(null);
} catch (Exception e) {
{if (true) throw new ParseException(
"Could not evaluate expression (on parse-time): " + paramExp.getCanonicalForm()
+ "\nUnderlying cause: " + e,
paramExp, e);}
}
String paramStr;
if (paramTM instanceof TemplateScalarModel) {
try {
paramStr = ((TemplateScalarModel) paramTM).getAsString();
} catch (TemplateModelException e) {
{if (true) throw new ParseException(
"Could not evaluate expression (on parse-time): " + paramExp.getCanonicalForm()
+ "\nUnderlying cause: " + e,
paramExp, e);}
}
} else {
{if (true) throw new ParseException(
"Parameter must be a string, but was: " + ClassUtil.getFTLTypeDescription(paramTM),
paramExp);}
}
lastOutputFormat = outputFormat;
try {
if (paramStr.startsWith("{")) {
if (!paramStr.endsWith("}")) {
{if (true) throw new ParseException("Output format name that starts with '{' must end with '}': " + paramStr,
template, start);}
}
OutputFormat innerOutputFormat = template.getConfiguration().getOutputFormat(
paramStr.substring(1, paramStr.length() - 1));
if (!(innerOutputFormat instanceof MarkupOutputFormat)) {
{if (true) throw new ParseException(
"The output format inside the {...} must be a markup format, but was: "
+ innerOutputFormat,
template, start);}
}
if (!(outputFormat instanceof MarkupOutputFormat)) {
{if (true) throw new ParseException(
"The current output format must be a markup format when using {...}, but was: "
+ outputFormat,
template, start);}
}
outputFormat = new CombinedMarkupOutputFormat(
(MarkupOutputFormat) outputFormat, (MarkupOutputFormat) innerOutputFormat);
} else {
outputFormat = template.getConfiguration().getOutputFormat(paramStr);
}
recalculateAutoEscapingField();
} catch (IllegalArgumentException e) {
{if (true) throw new ParseException("Invalid format name: " + e.getMessage(), template, start, e.getCause());}
} catch (UnregisteredOutputFormatException e) {
{if (true) throw new ParseException(e.getMessage(), template, start, e.getCause());}
}
children = MixedContentElements();
end = jj_consume_token(END_OUTPUTFORMAT);
OutputFormatBlock result = new OutputFormatBlock(children, paramExp);
result.setLocation(template, start, end);
outputFormat = lastOutputFormat;
recalculateAutoEscapingField();
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public AutoEscBlock AutoEsc() throws ParseException {Token start, end;
TemplateElements children;
int lastAutoEscapingPolicy;
start = jj_consume_token(AUTOESC);
checkCurrentOutputFormatCanEscape(start);
lastAutoEscapingPolicy = autoEscapingPolicy;
autoEscapingPolicy = Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY;
recalculateAutoEscapingField();
children = MixedContentElements();
end = jj_consume_token(END_AUTOESC);
AutoEscBlock result = new AutoEscBlock(children);
result.setLocation(template, start, end);
autoEscapingPolicy = lastAutoEscapingPolicy;
recalculateAutoEscapingField();
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public NoAutoEscBlock NoAutoEsc() throws ParseException {Token start, end;
TemplateElements children;
int lastAutoEscapingPolicy;
start = jj_consume_token(NOAUTOESC);
lastAutoEscapingPolicy = autoEscapingPolicy;
autoEscapingPolicy = Configuration.DISABLE_AUTO_ESCAPING_POLICY;
recalculateAutoEscapingField();
children = MixedContentElements();
end = jj_consume_token(END_NOAUTOESC);
NoAutoEscBlock result = new NoAutoEscBlock(children);
result.setLocation(template, start, end);
autoEscapingPolicy = lastAutoEscapingPolicy;
recalculateAutoEscapingField();
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production to terminate potentially empty elements. Either a ">" or "/>"
*/
final public Token LooseDirectiveEnd() throws ParseException {Token t;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case DIRECTIVE_END:{
t = jj_consume_token(DIRECTIVE_END);
break;
}
case EMPTY_DIRECTIVE_END:{
t = jj_consume_token(EMPTY_DIRECTIVE_END);
break;
}
default:
jj_la1[84] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
{if ("" != null) return t;}
throw new Error("Missing return statement in function");
}
final public PropertySetting Setting() throws ParseException {Token start, end, key;
Expression value;
start = jj_consume_token(SETTING);
key = jj_consume_token(ID);
jj_consume_token(EQUALS);
value = Expression();
end = LooseDirectiveEnd();
token_source.checkNamingConvention(key);
PropertySetting result = new PropertySetting(key, token_source, value, template.getConfiguration());
result.setLocation(template, start, end);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* A production for FreeMarker directives.
*/
final public TemplateElement FreemarkerDirective() throws ParseException {TemplateElement tp;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case IF:{
tp = If();
break;
}
case LIST:{
tp = List();
break;
}
case FOREACH:{
tp = ForEach();
break;
}
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:{
tp = Assign();
break;
}
case _INCLUDE:{
tp = Include();
break;
}
case IMPORT:{
tp = Import();
break;
}
case FUNCTION:
case MACRO:{
tp = Macro();
break;
}
case COMPRESS:{
tp = Compress();
break;
}
case UNIFIED_CALL:{
tp = UnifiedMacroTransform();
break;
}
case ITEMS:{
tp = Items();
break;
}
case SEP:{
tp = Sep();
break;
}
case CALL:{
tp = Call();
break;
}
case COMMENT:
case TERSE_COMMENT:{
tp = Comment();
break;
}
case NOPARSE:{
tp = NoParse();
break;
}
case TRANSFORM:{
tp = Transform();
break;
}
case SWITCH:{
tp = Switch();
break;
}
case SETTING:{
tp = Setting();
break;
}
case BREAK:{
tp = Break();
break;
}
case CONTINUE:{
tp = Continue();
break;
}
case RETURN:
case SIMPLE_RETURN:{
tp = Return();
break;
}
case STOP:
case HALT:{
tp = Stop();
break;
}
case FLUSH:{
tp = Flush();
break;
}
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:{
tp = Trim();
break;
}
case SIMPLE_NESTED:
case NESTED:{
tp = Nested();
break;
}
case ESCAPE:{
tp = Escape();
break;
}
case NOESCAPE:{
tp = NoEscape();
break;
}
case VISIT:{
tp = Visit();
break;
}
case SIMPLE_RECURSE:
case RECURSE:{
tp = Recurse();
break;
}
case FALLBACK:{
tp = FallBack();
break;
}
case ATTEMPT:{
tp = Attempt();
break;
}
case OUTPUTFORMAT:{
tp = OutputFormat();
break;
}
case AUTOESC:{
tp = AutoEsc();
break;
}
case NOAUTOESC:{
tp = NoAutoEsc();
break;
}
default:
jj_la1[85] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
{if ("" != null) return tp;}
throw new Error("Missing return statement in function");
}
/**
* Production for a block of raw text
* i.e. text that contains no
* FreeMarker directives.
*/
final public TextBlock PCData() throws ParseException {StringBuilder buf = new StringBuilder();
Token t = null, start = null, prevToken = null;
label_17:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:{
t = jj_consume_token(STATIC_TEXT_WS);
break;
}
case STATIC_TEXT_NON_WS:{
t = jj_consume_token(STATIC_TEXT_NON_WS);
break;
}
case STATIC_TEXT_FALSE_ALARM:{
t = jj_consume_token(STATIC_TEXT_FALSE_ALARM);
break;
}
default:
jj_la1[86] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
buf.append(t.image);
if (start == null) start = t;
if (prevToken != null) prevToken.next = null;
prevToken = t;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:{
;
break;
}
default:
jj_la1[87] = jj_gen;
break label_17;
}
}
if (stripText && mixedContentNesting == 1 && !preventStrippings) {if ("" != null) return null;}
TextBlock result = new TextBlock(buf.toString(), false);
result.setLocation(template, start, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
final public TextBlock WhitespaceText() throws ParseException {Token t = null, start = null;
t = jj_consume_token(STATIC_TEXT_WS);
if (stripText && mixedContentNesting == 1 && !preventStrippings) {if ("" != null) return null;}
TextBlock result = new TextBlock(t.image, false);
result.setLocation(template, t, t);
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Production for dealing with unparsed content,
* i.e. what is inside a comment or noparse tag.
* It returns the ending token. The content
* of the tag is put in buf.
*/
final public Token UnparsedContent(Token start, StringBuilder buf) throws ParseException {Token t;
label_18:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case KEEP_GOING:{
t = jj_consume_token(KEEP_GOING);
break;
}
case MAYBE_END:{
t = jj_consume_token(MAYBE_END);
break;
}
case TERSE_COMMENT_END:{
t = jj_consume_token(TERSE_COMMENT_END);
break;
}
case LONE_LESS_THAN_OR_DASH:{
t = jj_consume_token(LONE_LESS_THAN_OR_DASH);
break;
}
default:
jj_la1[88] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
buf.append(t.image);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TERSE_COMMENT_END:
case MAYBE_END:
case KEEP_GOING:
case LONE_LESS_THAN_OR_DASH:{
;
break;
}
default:
jj_la1[89] = jj_gen;
break label_18;
}
}
buf.setLength(buf.length() - t.image.length());
if (!t.image.endsWith(";")
&& _TemplateAPI.getTemplateLanguageVersionAsInt(template) >= _TemplateAPI.VERSION_INT_2_3_21) {
{if (true) throw new ParseException("Unclosed \"" + start.image + "\"", template, start);}
}
{if ("" != null) return t;}
throw new Error("Missing return statement in function");
}
final public TemplateElements MixedContentElements() throws ParseException {TemplateElement[] childBuffer = null;
int childCount = 0;
TemplateElement elem;
mixedContentNesting++;
label_19:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ATTEMPT:
case IF:
case LIST:
case ITEMS:
case SEP:
case FOREACH:
case SWITCH:
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:
case _INCLUDE:
case IMPORT:
case FUNCTION:
case MACRO:
case TRANSFORM:
case VISIT:
case STOP:
case RETURN:
case CALL:
case SETTING:
case OUTPUTFORMAT:
case AUTOESC:
case NOAUTOESC:
case COMPRESS:
case COMMENT:
case TERSE_COMMENT:
case NOPARSE:
case BREAK:
case CONTINUE:
case SIMPLE_RETURN:
case HALT:
case FLUSH:
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:
case SIMPLE_NESTED:
case NESTED:
case SIMPLE_RECURSE:
case RECURSE:
case FALLBACK:
case ESCAPE:
case NOESCAPE:
case UNIFIED_CALL:
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:
case DOLLAR_INTERPOLATION_OPENING:
case HASH_INTERPOLATION_OPENING:{
;
break;
}
default:
jj_la1[90] = jj_gen;
break label_19;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:{
elem = PCData();
break;
}
case DOLLAR_INTERPOLATION_OPENING:{
elem = StringOutput();
break;
}
case HASH_INTERPOLATION_OPENING:{
elem = NumericalOutput();
break;
}
case ATTEMPT:
case IF:
case LIST:
case ITEMS:
case SEP:
case FOREACH:
case SWITCH:
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:
case _INCLUDE:
case IMPORT:
case FUNCTION:
case MACRO:
case TRANSFORM:
case VISIT:
case STOP:
case RETURN:
case CALL:
case SETTING:
case OUTPUTFORMAT:
case AUTOESC:
case NOAUTOESC:
case COMPRESS:
case COMMENT:
case TERSE_COMMENT:
case NOPARSE:
case BREAK:
case CONTINUE:
case SIMPLE_RETURN:
case HALT:
case FLUSH:
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:
case SIMPLE_NESTED:
case NESTED:
case SIMPLE_RECURSE:
case RECURSE:
case FALLBACK:
case ESCAPE:
case NOESCAPE:
case UNIFIED_CALL:{
elem = FreemarkerDirective();
break;
}
default:
jj_la1[91] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
// Note: elem == null when it's was top-level PCData removed by stripText
if (elem != null) {
childCount++;
if (childBuffer == null) {
childBuffer = new TemplateElement[16];
} else if (childBuffer.length < childCount) {
TemplateElement[] newChildBuffer = new TemplateElement[childCount * 2];
for (int i = 0; i < childBuffer.length; i++) {
newChildBuffer[i] = childBuffer[i];
}
childBuffer = newChildBuffer;
}
childBuffer[childCount - 1] = elem;
}
}
mixedContentNesting--;
{if ("" != null) return childBuffer != null ? new TemplateElements(childBuffer, childCount) : TemplateElements.EMPTY;}
throw new Error("Missing return statement in function");
}
/**
* Not used anymore; kept for backward compatibility.
*
* @deprecated Use {@link #MixedContentElements} instead.
*/
final public MixedContent MixedContent() throws ParseException {MixedContent mixedContent = new MixedContent();
TemplateElement elem, begin = null;
mixedContentNesting++;
label_20:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:{
elem = PCData();
break;
}
case DOLLAR_INTERPOLATION_OPENING:{
elem = StringOutput();
break;
}
case HASH_INTERPOLATION_OPENING:{
elem = NumericalOutput();
break;
}
case ATTEMPT:
case IF:
case LIST:
case ITEMS:
case SEP:
case FOREACH:
case SWITCH:
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:
case _INCLUDE:
case IMPORT:
case FUNCTION:
case MACRO:
case TRANSFORM:
case VISIT:
case STOP:
case RETURN:
case CALL:
case SETTING:
case OUTPUTFORMAT:
case AUTOESC:
case NOAUTOESC:
case COMPRESS:
case COMMENT:
case TERSE_COMMENT:
case NOPARSE:
case BREAK:
case CONTINUE:
case SIMPLE_RETURN:
case HALT:
case FLUSH:
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:
case SIMPLE_NESTED:
case NESTED:
case SIMPLE_RECURSE:
case RECURSE:
case FALLBACK:
case ESCAPE:
case NOESCAPE:
case UNIFIED_CALL:{
elem = FreemarkerDirective();
break;
}
default:
jj_la1[92] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (begin == null) {
begin = elem;
}
mixedContent.addElement(elem);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ATTEMPT:
case IF:
case LIST:
case ITEMS:
case SEP:
case FOREACH:
case SWITCH:
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:
case _INCLUDE:
case IMPORT:
case FUNCTION:
case MACRO:
case TRANSFORM:
case VISIT:
case STOP:
case RETURN:
case CALL:
case SETTING:
case OUTPUTFORMAT:
case AUTOESC:
case NOAUTOESC:
case COMPRESS:
case COMMENT:
case TERSE_COMMENT:
case NOPARSE:
case BREAK:
case CONTINUE:
case SIMPLE_RETURN:
case HALT:
case FLUSH:
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:
case SIMPLE_NESTED:
case NESTED:
case SIMPLE_RECURSE:
case RECURSE:
case FALLBACK:
case ESCAPE:
case NOESCAPE:
case UNIFIED_CALL:
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:
case DOLLAR_INTERPOLATION_OPENING:
case HASH_INTERPOLATION_OPENING:{
;
break;
}
default:
jj_la1[93] = jj_gen;
break label_20;
}
}
mixedContentNesting--;
mixedContent.setLocation(template, begin, elem);
{if ("" != null) return mixedContent;}
throw new Error("Missing return statement in function");
}
/**
* Not used anymore; kept for backward compatibility.
*
* A production for a block of optional content.
* Returns an empty Text block if there is no
* content.
*
* @deprecated Use {@link #MixedContentElements} instead.
*/
final public TemplateElement OptionalBlock() throws ParseException {TemplateElement tp = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ATTEMPT:
case IF:
case LIST:
case ITEMS:
case SEP:
case FOREACH:
case SWITCH:
case ASSIGN:
case GLOBALASSIGN:
case LOCALASSIGN:
case _INCLUDE:
case IMPORT:
case FUNCTION:
case MACRO:
case TRANSFORM:
case VISIT:
case STOP:
case RETURN:
case CALL:
case SETTING:
case OUTPUTFORMAT:
case AUTOESC:
case NOAUTOESC:
case COMPRESS:
case COMMENT:
case TERSE_COMMENT:
case NOPARSE:
case BREAK:
case CONTINUE:
case SIMPLE_RETURN:
case HALT:
case FLUSH:
case TRIM:
case LTRIM:
case RTRIM:
case NOTRIM:
case SIMPLE_NESTED:
case NESTED:
case SIMPLE_RECURSE:
case RECURSE:
case FALLBACK:
case ESCAPE:
case NOESCAPE:
case UNIFIED_CALL:
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:
case DOLLAR_INTERPOLATION_OPENING:
case HASH_INTERPOLATION_OPENING:{
// has no effect but to get rid of a spurious warning.
tp = MixedContent();
break;
}
default:
jj_la1[94] = jj_gen;
;
}
{if ("" != null) return tp != null ? tp : new TextBlock(CollectionUtils.EMPTY_CHAR_ARRAY, false);}
throw new Error("Missing return statement in function");
}
/**
* A production freemarker text that may contain
* ${...} and #{...} but no directives.
*/
final public TemplateElement FreeMarkerText() throws ParseException {MixedContent nodes = new MixedContent();
TemplateElement elem, begin = null;
label_21:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:{
elem = PCData();
break;
}
case DOLLAR_INTERPOLATION_OPENING:{
elem = StringOutput();
break;
}
case HASH_INTERPOLATION_OPENING:{
elem = NumericalOutput();
break;
}
default:
jj_la1[95] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (begin == null) {
begin = elem;
}
nodes.addChild(elem);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:
case STATIC_TEXT_NON_WS:
case STATIC_TEXT_FALSE_ALARM:
case DOLLAR_INTERPOLATION_OPENING:
case HASH_INTERPOLATION_OPENING:{
;
break;
}
default:
jj_la1[96] = jj_gen;
break label_21;
}
}
nodes.setLocation(template, begin, elem);
{if ("" != null) return nodes;}
throw new Error("Missing return statement in function");
}
/**
* To be used between tags that in theory has nothing between, such between #switch and the first #case.
*/
final public MixedContent WhitespaceAndComments() throws ParseException {MixedContent nodes = new MixedContent();
TemplateElement elem, begin = null;
label_22:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:{
elem = WhitespaceText();
break;
}
case COMMENT:
case TERSE_COMMENT:{
elem = Comment();
break;
}
default:
jj_la1[97] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
if (elem != null) { // not removed by stripText
if (begin == null) {
begin = elem;
}
nodes.addChild(elem);
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMENT:
case TERSE_COMMENT:
case STATIC_TEXT_WS:{
;
break;
}
default:
jj_la1[98] = jj_gen;
break label_22;
}
}
if (begin == null // Was is removed by stripText?
// Nodes here won't be ever executed anyway, but whitespace stripping should still remove the
// lonely TextBlock from the AST, as that's purely source code formatting. If it's not lonely, then
// there must be a comment, in which case the generic whitespace stripping algorithm will kick in.
|| stripWhitespace && !preventStrippings
&& nodes.getChildCount() == 1 && nodes.getChild(0) instanceof TextBlock) {
{if ("" != null) return null;}
}
nodes.setLocation(template, begin, elem);
{if ("" != null) return nodes;}
throw new Error("Missing return statement in function");
}
final public void HeaderElement() throws ParseException {Token key;
Expression exp = null;
Token autoEscRequester = null;
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case STATIC_TEXT_WS:{
jj_consume_token(STATIC_TEXT_WS);
break;
}
default:
jj_la1[99] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case TRIVIAL_FTL_HEADER:{
jj_consume_token(TRIVIAL_FTL_HEADER);
break;
}
case FTL_HEADER:{
jj_consume_token(FTL_HEADER);
label_23:
while (true) {
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[100] = jj_gen;
break label_23;
}
key = jj_consume_token(ID);
jj_consume_token(EQUALS);
exp = Expression();
token_source.checkNamingConvention(key);
String ks = key.image;
TemplateModel value = null;
try {
value = exp.eval(null);
} catch (Exception e) {
{if (true) throw new ParseException(
"Could not evaluate expression (on parse-time): " + exp.getCanonicalForm()
+ " \nUnderlying cause: " + e,
exp, e);}
}
String vs = null;
if (value instanceof TemplateScalarModel) {
try {
vs = ((TemplateScalarModel) exp).getAsString();
} catch (TemplateModelException tme) {}
}
if (template != null) {
if (ks.equalsIgnoreCase("encoding")) {
if (vs == null) {
{if (true) throw new ParseException("Expected a string constant for \"" + ks + "\".", exp);}
}
String encoding = template.getEncoding();
if (encoding != null && !encoding.equalsIgnoreCase(vs)) {
{if (true) throw new Template.WrongEncodingException(vs, encoding);}
}
} else if (ks.equalsIgnoreCase("STRIP_WHITESPACE") || ks.equals("stripWhitespace")) {
this.stripWhitespace = getBoolean(exp, true);
} else if (ks.equalsIgnoreCase("STRIP_TEXT") || ks.equals("stripText")) {
this.stripText = getBoolean(exp, true);
} else if (ks.equalsIgnoreCase("STRICT_SYNTAX") || ks.equals("strictSyntax")) {
this.token_source.strictEscapeSyntax = getBoolean(exp, true);
} else if (ks.equalsIgnoreCase("auto_esc") || ks.equals("autoEsc")) {
if (getBoolean(exp, false)) {
autoEscRequester = key;
autoEscapingPolicy = Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY;
} else {
autoEscapingPolicy = Configuration.DISABLE_AUTO_ESCAPING_POLICY;
}
recalculateAutoEscapingField();
_TemplateAPI.setAutoEscaping(template, autoEscaping);
} else if (ks.equalsIgnoreCase("output_format") || ks.equals("outputFormat")) {
if (vs == null) {
{if (true) throw new ParseException("Expected a string constant for \"" + ks + "\".", exp);}
}
try {
outputFormat = template.getConfiguration().getOutputFormat(vs);
} catch (IllegalArgumentException e) {
{if (true) throw new ParseException("Invalid format name: " + e.getMessage(), exp, e.getCause());}
} catch (UnregisteredOutputFormatException e) {
{if (true) throw new ParseException(e.getMessage(), exp, e.getCause());}
}
recalculateAutoEscapingField();
_TemplateAPI.setOutputFormat(template, outputFormat);
_TemplateAPI.setAutoEscaping(template, autoEscaping);
} else if (ks.equalsIgnoreCase("ns_prefixes") || ks.equals("nsPrefixes")) {
if (!(value instanceof TemplateHashModelEx)) {
{if (true) throw new ParseException("Expecting a hash of prefixes to namespace URI's.", exp);}
}
TemplateHashModelEx prefixMap = (TemplateHashModelEx) value;
try {
TemplateCollectionModel keys = prefixMap.keys();
for (TemplateModelIterator it = keys.iterator(); it.hasNext();) {
String prefix = ((TemplateScalarModel) it.next()).getAsString();
TemplateModel valueModel = prefixMap.get(prefix);
if (!(valueModel instanceof TemplateScalarModel)) {
{if (true) throw new ParseException("Non-string value in prefix to namespace hash.", exp);}
}
String nsURI = ((TemplateScalarModel) valueModel).getAsString();
try {
template.addPrefixNSMapping(prefix, nsURI);
} catch (IllegalArgumentException iae) {
{if (true) throw new ParseException(iae.getMessage(), exp);}
}
}
} catch (TemplateModelException tme) {
}
} else if (ks.equalsIgnoreCase("attributes")) {
if (!(value instanceof TemplateHashModelEx)) {
{if (true) throw new ParseException("Expecting a hash of attribute names to values.", exp);}
}
TemplateHashModelEx attributeMap = (TemplateHashModelEx) value;
try {
TemplateCollectionModel keys = attributeMap.keys();
for (TemplateModelIterator it = keys.iterator(); it.hasNext();) {
String attName = ((TemplateScalarModel) it.next()).getAsString();
Object attValue = DeepUnwrap.unwrap(attributeMap.get(attName));
template.setCustomAttribute(attName, attValue);
}
} catch (TemplateModelException tme) {
}
} else {
String correctName;
if (ks.equals("charset")) {
correctName = "encoding";
} else if (ks.equals("xmlns")) {
// [2.4] If camel case will be the default, update this
correctName
= token_source.namingConvention == Configuration.CAMEL_CASE_NAMING_CONVENTION
? "nsPrefixes" : "ns_prefixes";
} else if (ks.equals("auto_escape") || ks.equals("auto_escaping") || ks.equals("autoesc")) {
correctName = "auto_esc";
} else if (ks.equals("autoEscape") || ks.equals("autoEscaping")) {
correctName = "autoEsc";
} else {
correctName = null;
}
{if (true) throw new ParseException(
"Unknown FTL header parameter: " + key.image
+ (correctName == null ? "" : ". You may meant: " + correctName),
template, key);}
}
}
}
if (autoEscRequester != null) {
checkCurrentOutputFormatCanEscape(autoEscRequester);
}
LooseDirectiveEnd();
break;
}
default:
jj_la1[101] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
}
final public Map ParamList() throws ParseException {Identifier id;
Expression exp;
Map result = new HashMap();
label_24:
while (true) {
id = Identifier();
jj_consume_token(EQUALS);
exp = Expression();
result.put(id.toString(), exp);
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case COMMA:{
jj_consume_token(COMMA);
break;
}
default:
jj_la1[102] = jj_gen;
;
}
switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
case ID:{
;
break;
}
default:
jj_la1[103] = jj_gen;
break label_24;
}
}
{if ("" != null) return result;}
throw new Error("Missing return statement in function");
}
/**
* Parses the already un-escaped content of a string literal (input must not include the quotation marks).
*
* @return A {@link List} of {@link String}-s and {@link Interpolation}-s.
*/
final public List