All Downloads are FREE. Search and download functionalities are using the official Maven repository.

freemarker.core.FMParser Maven / Gradle / Ivy

Go to download

FreeMarker is a "template engine"; a generic tool to generate text output based on templates.

There is a newer version: 2.3.33
Show newest version
/* 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>.
        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 ", 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 StaticTextAndInterpolations() throws ParseException {Token t; Interpolation interpolation; StringBuilder staticTextCollector = null; ArrayList parts = new ArrayList(); label_25: 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: case DOLLAR_INTERPOLATION_OPENING: case HASH_INTERPOLATION_OPENING:{ ; break; } default: jj_la1[104] = jj_gen; break label_25; } switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) { case STATIC_TEXT_WS: case STATIC_TEXT_NON_WS: case STATIC_TEXT_FALSE_ALARM:{ 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[105] = jj_gen; jj_consume_token(-1); throw new ParseException(); } String s = t.image; if (s.length() != 0) { if (staticTextCollector == null) { staticTextCollector = new StringBuilder(t.image); } else { staticTextCollector.append(t.image); } } break; } case DOLLAR_INTERPOLATION_OPENING: case HASH_INTERPOLATION_OPENING:{ if (jj_2_14(2147483647)) { interpolation = StringOutput(); } else if (jj_2_15(2147483647)) { interpolation = NumericalOutput(); } else { jj_consume_token(-1); throw new ParseException(); } if (staticTextCollector != null) { parts.add(staticTextCollector.toString()); staticTextCollector.setLength(0); } parts.add(interpolation); break; } default: jj_la1[106] = jj_gen; jj_consume_token(-1); throw new ParseException(); } } if (staticTextCollector != null && staticTextCollector.length() != 0) { parts.add(staticTextCollector.toString()); } parts.trimToSize(); {if ("" != null) return parts;} throw new Error("Missing return statement in function"); } /** * Root production to be used when parsing * an entire file. */ final public TemplateElement Root() throws ParseException {TemplateElements children; if (jj_2_16(2147483647)) { HeaderElement(); } else { ; } children = MixedContentElements(); jj_consume_token(0); TemplateElement root = children.asSingleElement(); root.setFieldsForRootElement(); if (!preventStrippings) { root = root.postParseCleanup(stripWhitespace); } // The cleanup result is possibly an element from deeper: root.setFieldsForRootElement(); {if ("" != null) return root;} throw new Error("Missing return statement in function"); } private boolean jj_2_1(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_1(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(0, xla); } } private boolean jj_2_2(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_2(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(1, xla); } } private boolean jj_2_3(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_3(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(2, xla); } } private boolean jj_2_4(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_4(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(3, xla); } } private boolean jj_2_5(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_5(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(4, xla); } } private boolean jj_2_6(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_6(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(5, xla); } } private boolean jj_2_7(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_7(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(6, xla); } } private boolean jj_2_8(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_8(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(7, xla); } } private boolean jj_2_9(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_9(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(8, xla); } } private boolean jj_2_10(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_10(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(9, xla); } } private boolean jj_2_11(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_11(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(10, xla); } } private boolean jj_2_12(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_12(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(11, xla); } } private boolean jj_2_13(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_13(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(12, xla); } } private boolean jj_2_14(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_14(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(13, xla); } } private boolean jj_2_15(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_15(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(14, xla); } } private boolean jj_2_16(int xla) { jj_la = xla; jj_lastpos = jj_scanpos = token; try { return !jj_3_16(); } catch(LookaheadSuccess ls) { return true; } finally { jj_save(15, xla); } } private boolean jj_3R_50() { if (jj_scan_token(MINUS)) return true; return false; } private boolean jj_3R_100() { if (jj_scan_token(EXCLAM)) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_101()) jj_scanpos = xsp; return false; } private boolean jj_3R_96() { if (jj_3R_26()) return true; return false; } private boolean jj_3R_90() { if (jj_scan_token(OPEN_PAREN)) return true; if (jj_3R_77()) return true; if (jj_scan_token(CLOSE_PAREN)) return true; return false; } private boolean jj_3R_45() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(118)) { jj_scanpos = xsp; if (jj_3R_50()) return true; } if (jj_3R_47()) return true; return false; } private boolean jj_3R_92() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(151)) { jj_scanpos = xsp; if (jj_3R_100()) return true; } return false; } private boolean jj_3_11() { if (jj_scan_token(ID)) return true; if (jj_scan_token(EQUALS)) return true; return false; } private boolean jj_3R_95() { if (jj_scan_token(DOT_DOT_ASTERISK)) return true; return false; } private boolean jj_3R_94() { if (jj_scan_token(DOT_DOT_LESS)) return true; return false; } private boolean jj_3R_85() { if (jj_scan_token(DOT_DOT)) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_96()) jj_scanpos = xsp; return false; } private boolean jj_3R_83() { if (jj_3R_93()) return true; return false; } private boolean jj_3R_82() { if (jj_3R_92()) return true; return false; } private boolean jj_3R_81() { if (jj_3R_91()) return true; return false; } private boolean jj_3R_84() { Token xsp; xsp = jj_scanpos; if (jj_3R_94()) { jj_scanpos = xsp; if (jj_3R_95()) return true; } if (jj_3R_26()) return true; return false; } private boolean jj_3R_80() { if (jj_3R_90()) return true; return false; } private boolean jj_3R_51() { if (jj_scan_token(EXCLAM)) return true; return false; } private boolean jj_3R_79() { if (jj_3R_89()) return true; return false; } private boolean jj_3R_78() { if (jj_3R_88()) return true; return false; } private boolean jj_3R_89() { if (jj_scan_token(OPEN_BRACKET)) return true; if (jj_3R_27()) return true; if (jj_scan_token(CLOSE_BRACKET)) return true; return false; } private boolean jj_3R_46() { Token xsp; if (jj_3R_51()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_51()) { jj_scanpos = xsp; break; } } if (jj_3R_47()) return true; return false; } private boolean jj_3R_72() { Token xsp; xsp = jj_scanpos; if (jj_3R_84()) { jj_scanpos = xsp; if (jj_3R_85()) return true; } return false; } private boolean jj_3R_71() { Token xsp; xsp = jj_scanpos; if (jj_3R_78()) { jj_scanpos = xsp; if (jj_3R_79()) { jj_scanpos = xsp; if (jj_3R_80()) { jj_scanpos = xsp; if (jj_3R_81()) { jj_scanpos = xsp; if (jj_3R_82()) { jj_scanpos = xsp; if (jj_3R_83()) return true; } } } } } return false; } private boolean jj_3R_61() { if (jj_3R_26()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_72()) jj_scanpos = xsp; return false; } private boolean jj_3R_39() { if (jj_3R_47()) return true; return false; } private boolean jj_3R_38() { if (jj_3R_46()) return true; return false; } private boolean jj_3R_37() { if (jj_3R_45()) return true; return false; } private boolean jj_3R_31() { Token xsp; xsp = jj_scanpos; if (jj_3R_37()) { jj_scanpos = xsp; if (jj_3R_38()) { jj_scanpos = xsp; if (jj_3R_39()) return true; } } return false; } private boolean jj_3R_97() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(128)) jj_scanpos = xsp; if (jj_3R_27()) return true; return false; } private boolean jj_3_5() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(149)) { jj_scanpos = xsp; if (jj_scan_token(117)) { jj_scanpos = xsp; if (jj_scan_token(148)) { jj_scanpos = xsp; if (jj_scan_token(116)) { jj_scanpos = xsp; if (jj_scan_token(115)) { jj_scanpos = xsp; if (jj_scan_token(115)) { jj_scanpos = xsp; if (jj_scan_token(114)) return true; } } } } } } return false; } private boolean jj_3R_87() { if (jj_3R_27()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_97()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3_16() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(79)) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(77)) { jj_scanpos = xsp; if (jj_scan_token(76)) return true; } return false; } private boolean jj_3R_98() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(114)) { jj_scanpos = xsp; if (jj_scan_token(115)) { jj_scanpos = xsp; if (jj_scan_token(116)) { jj_scanpos = xsp; if (jj_scan_token(117)) { jj_scanpos = xsp; if (jj_scan_token(94)) { jj_scanpos = xsp; if (jj_scan_token(95)) { jj_scanpos = xsp; if (jj_scan_token(137)) { jj_scanpos = xsp; if (jj_scan_token(138)) { jj_scanpos = xsp; if (jj_scan_token(139)) return true; } } } } } } } } return false; } private boolean jj_3R_70() { if (jj_scan_token(DOT)) return true; if (jj_scan_token(ID)) return true; return false; } private boolean jj_3R_77() { Token xsp; xsp = jj_scanpos; if (jj_3R_87()) jj_scanpos = xsp; return false; } private boolean jj_3R_62() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(149)) { jj_scanpos = xsp; if (jj_scan_token(117)) { jj_scanpos = xsp; if (jj_scan_token(148)) { jj_scanpos = xsp; if (jj_scan_token(116)) { jj_scanpos = xsp; if (jj_scan_token(115)) { jj_scanpos = xsp; if (jj_scan_token(114)) return true; } } } } } if (jj_3R_61()) return true; return false; } private boolean jj_3_1() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(98)) { jj_scanpos = xsp; if (jj_scan_token(131)) { jj_scanpos = xsp; if (jj_scan_token(133)) { jj_scanpos = xsp; if (jj_scan_token(102)) { jj_scanpos = xsp; if (jj_scan_token(127)) { jj_scanpos = xsp; if (jj_scan_token(151)) { jj_scanpos = xsp; if (jj_scan_token(103)) return true; } } } } } } return false; } private boolean jj_3R_69() { if (jj_scan_token(OPEN_PAREN)) return true; if (jj_3R_27()) return true; if (jj_scan_token(CLOSE_PAREN)) return true; return false; } private boolean jj_3R_88() { if (jj_scan_token(DOT)) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(140)) { jj_scanpos = xsp; if (jj_scan_token(120)) { jj_scanpos = xsp; if (jj_scan_token(121)) { jj_scanpos = xsp; if (jj_3R_98()) return true; } } } return false; } private boolean jj_3R_48() { if (jj_3R_61()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_62()) jj_scanpos = xsp; return false; } private boolean jj_3R_60() { if (jj_3R_71()) return true; return false; } private boolean jj_3R_59() { if (jj_3R_70()) return true; return false; } private boolean jj_3R_58() { if (jj_3R_69()) return true; return false; } private boolean jj_3R_57() { if (jj_3R_68()) return true; return false; } private boolean jj_3R_56() { if (jj_3R_67()) return true; return false; } private boolean jj_3_4() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(106)) { jj_scanpos = xsp; if (jj_scan_token(104)) { jj_scanpos = xsp; if (jj_scan_token(105)) return true; } } return false; } private boolean jj_3R_55() { if (jj_3R_66()) return true; return false; } private boolean jj_3_15() { if (jj_scan_token(HASH_INTERPOLATION_OPENING)) return true; return false; } private boolean jj_3_14() { if (jj_scan_token(DOLLAR_INTERPOLATION_OPENING)) return true; return false; } private boolean jj_3R_54() { if (jj_3R_65()) return true; return false; } private boolean jj_3R_68() { if (jj_scan_token(ID)) return true; return false; } private boolean jj_3R_53() { if (jj_3R_64()) return true; return false; } private boolean jj_3R_52() { if (jj_3R_63()) return true; return false; } private boolean jj_3R_99() { if (jj_scan_token(OPEN_PAREN)) return true; if (jj_3R_77()) return true; if (jj_scan_token(CLOSE_PAREN)) return true; return false; } private boolean jj_3R_49() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(106)) { jj_scanpos = xsp; if (jj_scan_token(104)) { jj_scanpos = xsp; if (jj_scan_token(105)) return true; } } if (jj_3R_48()) return true; return false; } private boolean jj_3_12() { if (jj_scan_token(OPEN_PAREN)) return true; return false; } private boolean jj_3R_47() { Token xsp; xsp = jj_scanpos; if (jj_3R_52()) { jj_scanpos = xsp; if (jj_3R_53()) { jj_scanpos = xsp; if (jj_3R_54()) { jj_scanpos = xsp; if (jj_3R_55()) { jj_scanpos = xsp; if (jj_3R_56()) { jj_scanpos = xsp; if (jj_3R_57()) { jj_scanpos = xsp; if (jj_3R_58()) { jj_scanpos = xsp; if (jj_3R_59()) return true; } } } } } } } while (true) { xsp = jj_scanpos; if (jj_3R_60()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_86() { if (jj_scan_token(COMMA)) return true; if (jj_3R_27()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(128)) { jj_scanpos = xsp; if (jj_scan_token(130)) return true; } if (jj_3R_27()) return true; return false; } private boolean jj_3R_43() { if (jj_3R_48()) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_49()) jj_scanpos = xsp; return false; } private boolean jj_3_13() { if (jj_scan_token(ID)) return true; if (jj_scan_token(EQUALS)) return true; return false; } private boolean jj_3R_63() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(96)) { jj_scanpos = xsp; if (jj_scan_token(97)) return true; } return false; } private boolean jj_3R_27() { if (jj_3R_30()) return true; return false; } private boolean jj_3R_42() { if (jj_scan_token(PERCENT)) return true; return false; } private boolean jj_3R_73() { if (jj_3R_27()) return true; Token xsp; xsp = jj_scanpos; if (jj_scan_token(128)) { jj_scanpos = xsp; if (jj_scan_token(130)) return true; } if (jj_3R_27()) return true; while (true) { xsp = jj_scanpos; if (jj_3R_86()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_41() { if (jj_scan_token(DIVIDE)) return true; return false; } private boolean jj_3R_40() { if (jj_scan_token(TIMES)) return true; return false; } private boolean jj_3_3() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(120)) { jj_scanpos = xsp; if (jj_scan_token(123)) { jj_scanpos = xsp; if (jj_scan_token(124)) return true; } } return false; } private boolean jj_3R_64() { if (jj_scan_token(OPENING_CURLY_BRACKET)) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_73()) jj_scanpos = xsp; if (jj_scan_token(CLOSING_CURLY_BRACKET)) return true; return false; } private boolean jj_3R_67() { if (jj_scan_token(OPEN_BRACKET)) return true; if (jj_3R_77()) return true; if (jj_scan_token(CLOSE_BRACKET)) return true; return false; } private boolean jj_3R_32() { Token xsp; xsp = jj_scanpos; if (jj_3R_40()) { jj_scanpos = xsp; if (jj_3R_41()) { jj_scanpos = xsp; if (jj_3R_42()) return true; } } if (jj_3R_31()) return true; return false; } private boolean jj_3_8() { if (jj_scan_token(OR)) return true; return false; } private boolean jj_3R_76() { if (jj_scan_token(TRUE)) return true; return false; } private boolean jj_3R_28() { if (jj_3R_31()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_32()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_75() { if (jj_scan_token(FALSE)) return true; return false; } private boolean jj_3_10() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(128)) jj_scanpos = xsp; xsp = jj_scanpos; if (jj_scan_token(140)) { jj_scanpos = xsp; if (jj_scan_token(92)) return true; } xsp = jj_scanpos; if (jj_scan_token(104)) { jj_scanpos = xsp; if (jj_scan_token(107)) { jj_scanpos = xsp; if (jj_scan_token(108)) { jj_scanpos = xsp; if (jj_scan_token(109)) { jj_scanpos = xsp; if (jj_scan_token(110)) { jj_scanpos = xsp; if (jj_scan_token(111)) { jj_scanpos = xsp; if (jj_scan_token(112)) { jj_scanpos = xsp; if (jj_scan_token(113)) return true; } } } } } } } return false; } private boolean jj_3R_66() { Token xsp; xsp = jj_scanpos; if (jj_3R_75()) { jj_scanpos = xsp; if (jj_3R_76()) return true; } return false; } private boolean jj_3R_36() { if (jj_scan_token(OR)) return true; if (jj_3R_35()) return true; return false; } private boolean jj_3R_30() { if (jj_3R_35()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_36()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_91() { if (jj_scan_token(BUILT_IN)) return true; if (jj_scan_token(ID)) return true; Token xsp; xsp = jj_scanpos; if (jj_3R_99()) jj_scanpos = xsp; return false; } private boolean jj_3_7() { if (jj_scan_token(AND)) return true; return false; } private boolean jj_3R_34() { if (jj_scan_token(MINUS)) return true; return false; } private boolean jj_3R_33() { if (jj_scan_token(PLUS)) return true; return false; } private boolean jj_3_2() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(118)) { jj_scanpos = xsp; if (jj_scan_token(119)) return true; } return false; } private boolean jj_3R_44() { if (jj_scan_token(AND)) return true; if (jj_3R_43()) return true; return false; } private boolean jj_3_9() { if (jj_3R_27()) return true; return false; } private boolean jj_3R_93() { if (jj_scan_token(EXISTS)) return true; return false; } private boolean jj_3R_29() { Token xsp; xsp = jj_scanpos; if (jj_3R_33()) { jj_scanpos = xsp; if (jj_3R_34()) return true; } if (jj_3R_28()) return true; return false; } private boolean jj_3R_35() { if (jj_3R_43()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_44()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_74() { if (jj_scan_token(RAW_STRING)) return true; return false; } private boolean jj_3R_26() { if (jj_3R_28()) return true; Token xsp; while (true) { xsp = jj_scanpos; if (jj_3R_29()) { jj_scanpos = xsp; break; } } return false; } private boolean jj_3R_101() { if (jj_3R_27()) return true; return false; } private boolean jj_3R_65() { Token xsp; xsp = jj_scanpos; if (jj_scan_token(92)) { jj_scanpos = xsp; if (jj_3R_74()) return true; } return false; } private boolean jj_3_6() { if (jj_3R_26()) return true; return false; } /** Generated Token Manager. */ public FMParserTokenManager token_source; SimpleCharStream jj_input_stream; /** Current token. */ public Token token; /** Next token. */ public Token jj_nt; private int jj_ntk; private Token jj_scanpos, jj_lastpos; private int jj_la; private int jj_gen; final private int[] jj_la1 = new int[107]; static private int[] jj_la1_0; static private int[] jj_la1_1; static private int[] jj_la1_2; static private int[] jj_la1_3; static private int[] jj_la1_4; static { jj_la1_init_0(); jj_la1_init_1(); jj_la1_init_2(); jj_la1_init_3(); jj_la1_init_4(); } private static void jj_la1_init_0() { jj_la1_0 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000000,0x2000000,0x0,0x0,0x70000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000,0x0,0x8000,0x8000,0x0,0xffff7d40,0x0,0x0,0x0,0x0,0xffff7d40,0xffff7d40,0xffff7d40,0xffff7d40,0xffff7d40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; } private static void jj_la1_init_1() { jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,0x300,0x0,0x0,0x400000,0x0,0x80,0x0,0x0,0x0,0x0,0x2000000,0x4000000,0x0,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x0,0xff80000f,0x0,0x0,0x0,0x0,0xff80000f,0xff80000f,0xff80000f,0xff80000f,0xff80000f,0x0,0x0,0x6,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; } private static void jj_la1_init_2() { jj_la1_2 = new int[] {0xf0000000,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0xc0000000,0xc0000000,0x30000000,0xc0000000,0x0,0x0,0x0,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0x18,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0xf0000000,0x0,0x0,0x0,0x0,0x8000,0x1,0x8000,0x1,0x1,0x0,0x57e,0x38000,0x38000,0x0,0x0,0xf857e,0xf857e,0xf857e,0xf857e,0xf857e,0xf8000,0xf8000,0x8000,0x8000,0x8000,0x0,0x3000,0x0,0x0,0xf8000,0x38000,0xf8000,}; } private static void jj_la1_init_3() { jj_la1_3 = new int[] {0x7,0x80c00007,0x80000000,0xc00000,0xc00000,0x19000000,0x700,0x3c0000,0x30,0x38,0x38,0x3,0x0,0x800000c4,0x80000000,0x3c0000,0x33c0000,0x0,0x0,0x0,0x0,0x0,0x80c00007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80c00007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf900,0x30000,0x3f900,0x0,0xf900,0x30000,0x3f900,0x0,0x0,0x0,0x3f900,0x0,0x0,0x0,0x0,0x0,0x4000000,0x100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80c00007,0x0,0x80c00007,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,}; } private static void jj_la1_init_4() { jj_la1_4 = new int[] {0x10a8,0x10a8,0x0,0x0,0x0,0x0,0x0,0x300000,0x0,0x0,0x0,0x0,0x1000,0x800028,0x800000,0xe00,0x1e00,0x0,0x0,0x5,0x1,0x5,0x10a8,0x2,0x0,0x0,0x0,0x1,0x400,0x0,0x1,0x0,0x800,0x10a8,0x800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x200,0x200,0x0,0x40200,0x2,0x1000,0x0,0x20,0x1000,0x0,0x0,0x1,0x40,0x0,0x400000,0x400000,0x400001,0x400000,0x400000,0x401000,0x2,0xc0000,0x40,0x1000,0x10a9,0x1,0x10a8,0x0,0x2,0x1000,0xc0000,0x0,0x0,0x0,0x0,0x0,0xc0000,0x0,0x0,0x0,0xf000000,0xf000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x0,0x1,0x1000,0x0,0x0,0x0,}; } final private JJCalls[] jj_2_rtns = new JJCalls[16]; private boolean jj_rescan = false; private int jj_gc = 0; /** Constructor with InputStream. */ public FMParser(java.io.InputStream stream) { this(stream, null); } /** Constructor with InputStream and supplied encoding */ public FMParser(java.io.InputStream stream, String encoding) { try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source = new FMParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(java.io.InputStream stream) { ReInit(stream, null); } /** Reinitialise. */ public void ReInit(java.io.InputStream stream, String encoding) { try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); } token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Constructor. */ public FMParser(java.io.Reader stream) { jj_input_stream = new SimpleCharStream(stream, 1, 1); token_source = new FMParserTokenManager(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(java.io.Reader stream) { if (jj_input_stream == null) { jj_input_stream = new SimpleCharStream(stream, 1, 1); } else { jj_input_stream.ReInit(stream, 1, 1); } if (token_source == null) { token_source = new FMParserTokenManager(jj_input_stream); } token_source.ReInit(jj_input_stream); token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Constructor with generated Token Manager. */ public FMParser(FMParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } /** Reinitialise. */ public void ReInit(FMParserTokenManager tm) { token_source = tm; token = new Token(); jj_ntk = -1; jj_gen = 0; for (int i = 0; i < 107; i++) jj_la1[i] = -1; for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls(); } private Token jj_consume_token(int kind) throws ParseException { Token oldToken; if ((oldToken = token).next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; if (token.kind == kind) { jj_gen++; if (++jj_gc > 100) { jj_gc = 0; for (int i = 0; i < jj_2_rtns.length; i++) { JJCalls c = jj_2_rtns[i]; while (c != null) { if (c.gen < jj_gen) c.first = null; c = c.next; } } } return token; } token = oldToken; jj_kind = kind; throw generateParseException(); } @SuppressWarnings("serial") static private final class LookaheadSuccess extends java.lang.Error { } final private LookaheadSuccess jj_ls = new LookaheadSuccess(); private boolean jj_scan_token(int kind) { if (jj_scanpos == jj_lastpos) { jj_la--; if (jj_scanpos.next == null) { jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken(); } else { jj_lastpos = jj_scanpos = jj_scanpos.next; } } else { jj_scanpos = jj_scanpos.next; } if (jj_rescan) { int i = 0; Token tok = token; while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; } if (tok != null) jj_add_error_token(kind, i); } if (jj_scanpos.kind != kind) return true; if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls; return false; } /** Get the next Token. */ final public Token getNextToken() { if (token.next != null) token = token.next; else token = token.next = token_source.getNextToken(); jj_ntk = -1; jj_gen++; return token; } /** Get the specific Token. */ final public Token getToken(int index) { Token t = token; for (int i = 0; i < index; i++) { if (t.next != null) t = t.next; else t = t.next = token_source.getNextToken(); } return t; } private int jj_ntk_f() { if ((jj_nt=token.next) == null) return (jj_ntk = (token.next=token_source.getNextToken()).kind); else return (jj_ntk = jj_nt.kind); } private java.util.List jj_expentries = new java.util.ArrayList(); private int[] jj_expentry; private int jj_kind = -1; private int[] jj_lasttokens = new int[100]; private int jj_endpos; private void jj_add_error_token(int kind, int pos) { if (pos >= 100) { return; } if (pos == jj_endpos + 1) { jj_lasttokens[jj_endpos++] = kind; } else if (jj_endpos != 0) { jj_expentry = new int[jj_endpos]; for (int i = 0; i < jj_endpos; i++) { jj_expentry[i] = jj_lasttokens[i]; } for (int[] oldentry : jj_expentries) { if (oldentry.length == jj_expentry.length) { boolean isMatched = true; for (int i = 0; i < jj_expentry.length; i++) { if (oldentry[i] != jj_expentry[i]) { isMatched = false; break; } } if (isMatched) { jj_expentries.add(jj_expentry); break; } } } if (pos != 0) { jj_lasttokens[(jj_endpos = pos) - 1] = kind; } } } /** Generate ParseException. */ public ParseException generateParseException() { jj_expentries.clear(); boolean[] la1tokens = new boolean[156]; if (jj_kind >= 0) { la1tokens[jj_kind] = true; jj_kind = -1; } for (int i = 0; i < 107; i++) { if (jj_la1[i] == jj_gen) { for (int j = 0; j < 32; j++) { if ((jj_la1_0[i] & (1< jj_gen) { jj_la = p.arg; jj_lastpos = jj_scanpos = p.first; switch (i) { case 0: jj_3_1(); break; case 1: jj_3_2(); break; case 2: jj_3_3(); break; case 3: jj_3_4(); break; case 4: jj_3_5(); break; case 5: jj_3_6(); break; case 6: jj_3_7(); break; case 7: jj_3_8(); break; case 8: jj_3_9(); break; case 9: jj_3_10(); break; case 10: jj_3_11(); break; case 11: jj_3_12(); break; case 12: jj_3_13(); break; case 13: jj_3_14(); break; case 14: jj_3_15(); break; case 15: jj_3_16(); break; } } p = p.next; } while (p != null); } catch(LookaheadSuccess ls) { } } jj_rescan = false; } private void jj_save(int index, int xla) { JJCalls p = jj_2_rtns[index]; while (p.gen > jj_gen) { if (p.next == null) { p = p.next = new JJCalls(); break; } p = p.next; } p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla; } static final class JJCalls { int gen; Token first; int arg; JJCalls next; } }