Generates (prop, value) pairs from declarations

        In a future version may generate parsed tokens from tinycss/tinycss2
545025
def parse(self, declarations_str):
        
        for decl in declarations_str.split(';'):
            if not decl.strip():
                continue
            prop, sep, val = decl.partition(':')
            prop = prop.strip().lower()
            # TODO: don't lowercase case sensitive parts of values (strings)
            val = val.strip().lower()
            if sep:
                yield prop, val
            else:
                warnings.warn('Ill-formatted attribute: expected a colon '
                              'in {decl!r}'.format(decl=decl), CSSWarning)
678303
private Statement generateIncrementalDomRenderCalls(TemplateNode node, String alias) {
    IncrementalDomCodeBuilder jsCodeBuilder = getJsCodeBuilder();
    boolean isTextTemplate = isTextContent(node.getContentKind());

    Statement typeChecks = genParamTypeChecks(node, alias);
    // Note: we do not try to combine this into a single return statement if the content is
    // computable as a JsExpr. A JavaScript compiler, such as Closure Compiler, is able to perform
    // the transformation.
    if (isTextTemplate) {
      // We do our own initialization below, so mark it as such.
      jsCodeBuilder.pushOutputVar("output").setOutputVarInited();
    }
    Statement body = visitChildrenReturningCodeChunk(node);

    if (isTextTemplate) {
      VariableDeclaration declare =
          VariableDeclaration.builder("output").setRhs(LITERAL_EMPTY_STRING).build();
      jsCodeBuilder.popOutputVar();
      body =
          Statement.of(declare, body, returnValue(sanitize(declare.ref(), node.getContentKind())));
    }
    return Statement.of(typeChecks, body);
  }
544036
function generateJS( ast, session, options ) {

    const op = session.opcodes;

    /* Features that should be generated in the parser. */
    const features = options.features || {};
    function use( feature, use ) {

        return feature in features
            ? !! features[ feature ]
            : use == null
            ? true
            : !! use;

    }

    /* These only indent non-empty lines to avoid trailing whitespace. */
    const lineMatchRE = /^([^`\r\n]+?(?:`[^`]*?`[^\r\n]*?)?)$/gm;
    function indent2( code ) {

        return code.replace( lineMatchRE, "  $1" );

    }
    function indent10( code ) {

        return code.replace( lineMatchRE, "          $1" );

    }

    const l = i => "peg$c" + i; // |literals[i]| of the abstract machine
    const r = i => "peg$r" + i; // |classes[i]| of the abstract machine
    const e = i => "peg$e" + i; // |expectations[i]| of the abstract machine
    const f = i => "peg$f" + i; // |actions[i]| of the abstract machine

    function generateTables() {

        function buildLiteral( literal ) {

            return `"${ util.stringEscape( literal ) }"`;

        }

        function buildRegexp( cls ) {

            return "/^["
                + ( cls.inverted ? "^" : "" )
                + cls.value
                    .map( part => (

                        Array.isArray( part )
                            ? util.regexpEscape( part[ 0 ] )
                                + "-"
                                + util.regexpEscape( part[ 1 ] )
                            : util.regexpEscape( part )

                    ) )
                    .join( "" )
                + "]/"
                + ( cls.ignoreCase ? "i" : "" );

        }

        function buildExpectation( e ) {

            switch ( e.type ) {

                case "rule":
                    return `peg$otherExpectation("${ util.stringEscape( e.value ) }")`;

                case "literal":
                    return "peg$literalExpectation(\""
                           + util.stringEscape( e.value )
                           + "\", "
                           + e.ignoreCase
                           + ")";

                case "class": {

                    const parts = e.value.map( part =>
                        ( Array.isArray( part )
                            ? `["${ util.stringEscape( part[ 0 ] ) }", "${ util.stringEscape( part[ 1 ] ) }"]`
                            : `"${ util.stringEscape( part ) }"` )
                    );

                    return "peg$classExpectation(["
                           + parts.join( ", " ) + "], "
                           + e.inverted + ", "
                           + e.ignoreCase
                           + ")";

                }

                case "any":
                    return "peg$anyExpectation()";

                // istanbul ignore next
                default:
                    session.fatal( `Unknown expectation type (${ JSON.stringify( e ) })` );

            }

        }

        function buildFunc( f ) {

            return `function(${ f.params.join( ", " ) }) {${ f.body }}`;

        }

        if ( options.optimize === "size" ) {

            return [
                "var peg$literals = [",
                indent2( ast.literals.map( buildLiteral ).join( ",\n" ) ),
                "];",
                "var peg$regexps = [",
                indent2( ast.classes.map( buildRegexp ).join( ",\n" ) ),
                "];",
                "var peg$expectations = [",
                indent2( ast.expectations.map( buildExpectation ).join( ",\n" ) ),
                "];",
                "var peg$functions = [",
                indent2( ast.functions.map( buildFunc ).join( ",\n" ) ),
                "];",
                "",
                "var peg$bytecode = [",
                indent2( ast.rules
                    .map( rule =>
                        `peg$decode("${
                            util.stringEscape( rule.bytecode
                                .map( b => String.fromCharCode( b + 32 ) )
                                .join( "" )
                            )
                        }")`
                    )
                    .join( ",\n" )
                ),
                "];"
            ].join( "\n" );

        }

        return ast.literals
            .map( ( c, i ) => "var " + l( i ) + " = " + buildLiteral( c ) + ";" )
            .concat( "", ast.classes.map(
                ( c, i ) => "var " + r( i ) + " = " + buildRegexp( c ) + ";"
            ) )
            .concat( "", ast.expectations.map(
                ( c, i ) => "var " + e( i ) + " = " + buildExpectation( c ) + ";"
            ) )
            .concat( "", ast.functions.map(
                ( c, i ) => "var " + f( i ) + " = " + buildFunc( c ) + ";"
            ) )
            .join( "\n" );

    }

    function generateRuleHeader( ruleNameCode, ruleIndexCode ) {

        const parts = [];

        parts.push( [
            "",
            "var rule$expects = function (expected) {",
            "  if (peg$silentFails === 0) peg$expect(expected);",
            "}",
            ""
        ].join( "\n" ) );

        if ( options.trace ) {

            parts.push( [
                "peg$tracer.trace({",
                "  type: \"rule.enter\",",
                "  rule: " + ruleNameCode + ",",
                "  location: peg$computeLocation(startPos, startPos)",
                "});",
                ""
            ].join( "\n" ) );

        }

        if ( options.cache ) {

            parts.push( [
                "var key = peg$currPos * " + ast.rules.length + " + " + ruleIndexCode + ";",
                "var cached = peg$resultsCache[key];",
                "var rule$expectations = [];",
                "",
                "rule$expects = function (expected) {",
                "  if (peg$silentFails === 0) peg$expect(expected);",
                "  rule$expectations.push(expected);",
                "}",
                "",
                "if (cached) {",
                "  peg$currPos = cached.nextPos;",
                "",
                "  rule$expectations = cached.expectations;",
                "  if (peg$silentFails === 0) {",
                "    rule$expectations.forEach(peg$expect);",
                "  }",
                ""
            ].join( "\n" ) );

            if ( options.trace ) {

                parts.push( [
                    "if (cached.result !== peg$FAILED) {",
                    "  peg$tracer.trace({",
                    "    type: \"rule.match\",",
                    "    rule: " + ruleNameCode + ",",
                    "    result: cached.result,",
                    "    location: peg$computeLocation(startPos, peg$currPos)",
                    "  });",
                    "} else {",
                    "  peg$tracer.trace({",
                    "    type: \"rule.fail\",",
                    "    rule: " + ruleNameCode + ",",
                    "    location: peg$computeLocation(startPos, startPos)",
                    "  });",
                    "}",
                    ""
                ].join( "\n" ) );

            }

            parts.push( [
                "  return cached.result;",
                "}",
                ""
            ].join( "\n" ) );

        }

        return parts.join( "\n" );

    }

    function generateRuleFooter( ruleNameCode, resultCode ) {

        const parts = [];

        if ( options.cache ) {

            parts.push( [
                "",
                "peg$resultsCache[key] = {",
                "  nextPos: peg$currPos,",
                "  result: " + resultCode + ",",
                "  expectations: rule$expectations",
                "};"
            ].join( "\n" ) );

        }

        if ( options.trace ) {

            parts.push( [
                "",
                "if (" + resultCode + " !== peg$FAILED) {",
                "  peg$tracer.trace({",
                "    type: \"rule.match\",",
                "    rule: " + ruleNameCode + ",",
                "    result: " + resultCode + ",",
                "    location: peg$computeLocation(startPos, peg$currPos)",
                "  });",
                "} else {",
                "  peg$tracer.trace({",
                "    type: \"rule.fail\",",
                "    rule: " + ruleNameCode + ",",
                "    location: peg$computeLocation(startPos, startPos)",
                "  });",
                "}"
            ].join( "\n" ) );

        }

        parts.push( [
            "",
            "return " + resultCode + ";"
        ].join( "\n" ) );

        return parts.join( "\n" );

    }

    function generateInterpreter() {

        const parts = [];

        function generateCondition( cond, argsLength ) {

            const baseLength = argsLength + 3;
            const thenLengthCode = "bc[ip + " + ( baseLength - 2 ) + "]";
            const elseLengthCode = "bc[ip + " + ( baseLength - 1 ) + "]";

            return [
                "ends.push(end);",
                "ips.push(ip + " + baseLength + " + " + thenLengthCode + " + " + elseLengthCode + ");",
                "",
                "if (" + cond + ") {",
                "  end = ip + " + baseLength + " + " + thenLengthCode + ";",
                "  ip += " + baseLength + ";",
                "} else {",
                "  end = ip + " + baseLength + " + " + thenLengthCode + " + " + elseLengthCode + ";",
                "  ip += " + baseLength + " + " + thenLengthCode + ";",
                "}",
                "",
                "break;"
            ].join( "\n" );

        }

        function generateLoop( cond ) {

            const baseLength = 2;
            const bodyLengthCode = "bc[ip + " + ( baseLength - 1 ) + "]";

            return [
                "if (" + cond + ") {",
                "  ends.push(end);",
                "  ips.push(ip);",
                "",
                "  end = ip + " + baseLength + " + " + bodyLengthCode + ";",
                "  ip += " + baseLength + ";",
                "} else {",
                "  ip += " + baseLength + " + " + bodyLengthCode + ";",
                "}",
                "",
                "break;"
            ].join( "\n" );

        }

        function generateCall() {

            const baseLength = 4;
            const paramsLengthCode = "bc[ip + " + ( baseLength - 1 ) + "]";

            return [
                "params = bc.slice(ip + " + baseLength + ", ip + " + baseLength + " + " + paramsLengthCode + ")",
                "  .map(function(p) { return stack[stack.length - 1 - p]; });",
                "",
                "stack.splice(",
                "  stack.length - bc[ip + 2],",
                "  bc[ip + 2],",
                "  peg$functions[bc[ip + 1]].apply(null, params)",
                ");",
                "",
                "ip += " + baseLength + " + " + paramsLengthCode + ";",
                "break;"
            ].join( "\n" );

        }

        parts.push( [
            "function peg$decode(s) {",
            "  return s.split(\"\").map(function(ch) { return ch.charCodeAt(0) - 32; });",
            "}",
            "",
            "function peg$parseRule(index) {"
        ].join( "\n" ) );

        if ( options.trace ) {

            parts.push( [
                "  var bc = peg$bytecode[index];",
                "  var ip = 0;",
                "  var ips = [];",
                "  var end = bc.length;",
                "  var ends = [];",
                "  var stack = [];",
                "  var startPos = peg$currPos;",
                "  var params, paramsLength, paramsN;"
            ].join( "\n" ) );

        } else {

            parts.push( [
                "  var bc = peg$bytecode[index];",
                "  var ip = 0;",
                "  var ips = [];",
                "  var end = bc.length;",
                "  var ends = [];",
                "  var stack = [];",
                "  var params, paramsLength, paramsN;"
            ].join( "\n" ) );

        }

        parts.push( indent2( generateRuleHeader( "peg$ruleNames[index]", "index" ) ) );

        parts.push( [
            // The point of the outer loop and the |ips| & |ends| stacks is to avoid
            // recursive calls for interpreting parts of bytecode. In other words, we
            // implement the |interpret| operation of the abstract machine without
            // function calls. Such calls would likely slow the parser down and more
            // importantly cause stack overflows for complex grammars.
            "  while (true) {",
            "    while (ip < end) {",
            "      switch (bc[ip]) {",
            "        case " + op.PUSH_EMPTY_STRING + ":",  // PUSH_EMPTY_STRING
            "          stack.push('');",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PUSH_UNDEFINED + ":",     // PUSH_UNDEFINED
            "          stack.push(undefined);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PUSH_NULL + ":",          // PUSH_NULL
            "          stack.push(null);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PUSH_FAILED + ":",        // PUSH_FAILED
            "          stack.push(peg$FAILED);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PUSH_EMPTY_ARRAY + ":",   // PUSH_EMPTY_ARRAY
            "          stack.push([]);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PUSH_CURR_POS + ":",      // PUSH_CURR_POS
            "          stack.push(peg$currPos);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.POP + ":",                // POP
            "          stack.pop();",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.POP_CURR_POS + ":",       // POP_CURR_POS
            "          peg$currPos = stack.pop();",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.POP_N + ":",              // POP_N n
            "          stack.length -= bc[ip + 1];",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.NIP + ":",                // NIP
            "          stack.splice(-2, 1);",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.APPEND + ":",             // APPEND
            "          stack[stack.length - 2].push(stack.pop());",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.WRAP + ":",               // WRAP n
            "          stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.TEXT + ":",               // TEXT
            "          stack.push(input.substring(stack.pop(), peg$currPos));",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.PLUCK + ":",               // PLUCK n, k, p1, ..., pK
            "          paramsLength = bc[ip + 2];",
            "          paramsN = 3 + paramsLength",
            "",
            "          params = bc.slice(ip + 3, ip + paramsN);",
            "          params = paramsLength === 1",
            "            ? stack[stack.length - 1 - params[ 0 ]]",
            "            : params.map(function(p) { return stack[stack.length - 1 - p]; });",
            "",
            "          stack.splice(",
            "            stack.length - bc[ip + 1],",
            "            bc[ip + 1],",
            "            params",
            "          );",
            "",
            "          ip += paramsN;",
            "          break;",
            "",
            "        case " + op.IF + ":",                 // IF t, f
            indent10( generateCondition( "stack[stack.length - 1]", 0 ) ),
            "",
            "        case " + op.IF_ERROR + ":",           // IF_ERROR t, f
            indent10( generateCondition(
                "stack[stack.length - 1] === peg$FAILED",
                0
            ) ),
            "",
            "        case " + op.IF_NOT_ERROR + ":",       // IF_NOT_ERROR t, f
            indent10(
                generateCondition( "stack[stack.length - 1] !== peg$FAILED",
                    0
                ) ),
            "",
            "        case " + op.WHILE_NOT_ERROR + ":",    // WHILE_NOT_ERROR b
            indent10( generateLoop( "stack[stack.length - 1] !== peg$FAILED" ) ),
            "",
            "        case " + op.MATCH_ANY + ":",          // MATCH_ANY a, f, ...
            indent10( generateCondition( "input.length > peg$currPos", 0 ) ),
            "",
            "        case " + op.MATCH_STRING + ":",       // MATCH_STRING s, a, f, ...
            indent10( generateCondition(
                "input.substr(peg$currPos, peg$literals[bc[ip + 1]].length) === peg$literals[bc[ip + 1]]",
                1
            ) ),
            "",
            "        case " + op.MATCH_STRING_IC + ":",    // MATCH_STRING_IC s, a, f, ...
            indent10( generateCondition(
                "input.substr(peg$currPos, peg$literals[bc[ip + 1]].length).toLowerCase() === peg$literals[bc[ip + 1]]",
                1
            ) ),
            "",
            "        case " + op.MATCH_CLASS + ":",        // MATCH_CLASS c, a, f, ...
            indent10( generateCondition(
                "peg$regexps[bc[ip + 1]].test(input.charAt(peg$currPos))",
                1
            ) ),
            "",
            "        case " + op.ACCEPT_N + ":",           // ACCEPT_N n
            "          stack.push(input.substr(peg$currPos, bc[ip + 1]));",
            "          peg$currPos += bc[ip + 1];",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.ACCEPT_STRING + ":",      // ACCEPT_STRING s
            "          stack.push(peg$literals[bc[ip + 1]]);",
            "          peg$currPos += peg$literals[bc[ip + 1]].length;",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.EXPECT + ":",             // EXPECT e
            "          rule$expects(peg$expectations[bc[ip + 1]]);",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.LOAD_SAVED_POS + ":",     // LOAD_SAVED_POS p
            "          peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.UPDATE_SAVED_POS + ":",   // UPDATE_SAVED_POS
            "          peg$savedPos = peg$currPos;",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.CALL + ":",               // CALL f, n, pc, p1, p2, ..., pN
            indent10( generateCall() ),
            "",
            "        case " + op.RULE + ":",               // RULE r
            "          stack.push(peg$parseRule(bc[ip + 1]));",
            "          ip += 2;",
            "          break;",
            "",
            "        case " + op.SILENT_FAILS_ON + ":",    // SILENT_FAILS_ON
            "          peg$silentFails++;",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.SILENT_FAILS_OFF + ":",   // SILENT_FAILS_OFF
            "          peg$silentFails--;",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.EXPECT_NS_BEGIN + ":",    // EXPECT_NS_BEGIN
            "          peg$begin();",
            "          ip++;",
            "          break;",
            "",
            "        case " + op.EXPECT_NS_END + ":",      // EXPECT_NS_END invert
            "          peg$end(bc[ip + 1]);",
            "          ip += 2;",
            "          break;",
            "",
            "        // istanbul ignore next",
            "        default:",
            "          throw new Error(",
            "            \"Rule #\" + index + \"" + ( options.trace ? " ('\" + peg$ruleNames[ index ] + \"')" : "" ) + ", position \" + ip + \": \"",
            "            + \"Invalid opcode \" + bc[ip] + \".\"",
            "          );",
            "      }",
            "    }",
            "",
            "    if (ends.length > 0) {",
            "      end = ends.pop();",
            "      ip = ips.pop();",
            "    } else {",
            "      break;",
            "    }",
            "  }"
        ].join( "\n" ) );

        parts.push( indent2( generateRuleFooter( "peg$ruleNames[index]", "stack[0]" ) ) );
        parts.push( "}" );

        return parts.join( "\n" );

    }

    function generateRuleFunction( rule ) {

        const parts = [];
        const stackVars = [];

        function s( i ) {

            // istanbul ignore next
            if ( i < 0 ) session.fatal( "Rule '" + rule.name + "': Var stack underflow: attempt to use var at index " + i );

            return "s" + i;

        } // |stack[i]| of the abstract machine

        const stack = {
            sp: -1,
            maxSp: -1,

            push( exprCode ) {

                const code = s( ++this.sp ) + " = " + exprCode + ";";
                if ( this.sp > this.maxSp ) this.maxSp = this.sp;
                return code;

            },

            pop( n ) {

                if ( typeof n === "undefined" ) return s( this.sp-- );

                const values = Array( n );

                for ( let i = 0; i < n; i++ ) {

                    values[ i ] = s( this.sp - n + 1 + i );

                }

                this.sp -= n;
                return values;

            },

            top() {

                return s( this.sp );

            },

            index( i ) {

                return s( this.sp - i );

            }
        };

        function compile( bc ) {

            let ip = 0;
            const end = bc.length;
            const parts = [];
            let value;

            function compileCondition( cond, argCount ) {

                const pos = ip;
                const baseLength = argCount + 3;
                const thenLength = bc[ ip + baseLength - 2 ];
                const elseLength = bc[ ip + baseLength - 1 ];
                const baseSp = stack.sp;
                let thenCode, elseCode, thenSp, elseSp;

                ip += baseLength;
                thenCode = compile( bc.slice( ip, ip + thenLength ) );
                thenSp = stack.sp;
                ip += thenLength;

                if ( elseLength > 0 ) {

                    stack.sp = baseSp;
                    elseCode = compile( bc.slice( ip, ip + elseLength ) );
                    elseSp = stack.sp;
                    ip += elseLength;

                    // istanbul ignore if
                    if ( thenSp !== elseSp ) {

                        session.fatal(
                            "Rule '" + rule.name + "', position " + pos + ": "
                            + "Branches of a condition can't move the stack pointer differently "
                            + "(before: " + baseSp + ", after then: " + thenSp + ", after else: " + elseSp + ")."
                        );

                    }

                }

                parts.push( "if (" + cond + ") {" );
                parts.push( indent2( thenCode ) );
                if ( elseLength > 0 ) {

                    parts.push( "} else {" );
                    parts.push( indent2( elseCode ) );

                }
                parts.push( "}" );

            }

            function compileLoop( cond ) {

                const pos = ip;
                const baseLength = 2;
                const bodyLength = bc[ ip + baseLength - 1 ];
                const baseSp = stack.sp;
                let bodyCode, bodySp;

                ip += baseLength;
                bodyCode = compile( bc.slice( ip, ip + bodyLength ) );
                bodySp = stack.sp;
                ip += bodyLength;

                // istanbul ignore if
                if ( bodySp !== baseSp ) {

                    session.fatal(
                        "Rule '" + rule.name + "', position " + pos + ": "
                        + "Body of a loop can't move the stack pointer "
                        + "(before: " + baseSp + ", after: " + bodySp + ")."
                    );

                }

                parts.push( "while (" + cond + ") {" );
                parts.push( indent2( bodyCode ) );
                parts.push( "}" );

            }

            function compileCall() {

                const baseLength = 4;
                const paramsLength = bc[ ip + baseLength - 1 ];

                const value = f( bc[ ip + 1 ] )
                    + "("
                    + bc
                        .slice( ip + baseLength, ip + baseLength + paramsLength )
                        .map( p => stack.index( p ) )
                        .join( ", " )
                    + ")";

                stack.pop( bc[ ip + 2 ] );
                parts.push( stack.push( value ) );
                ip += baseLength + paramsLength;

            }

            while ( ip < end ) {

                switch ( bc[ ip ] ) {

                    case op.PUSH_EMPTY_STRING:  // PUSH_EMPTY_STRING
                        parts.push( stack.push( "''" ) );
                        ip++;
                        break;

                    case op.PUSH_CURR_POS:      // PUSH_CURR_POS
                        parts.push( stack.push( "peg$currPos" ) );
                        ip++;
                        break;

                    case op.PUSH_UNDEFINED:     // PUSH_UNDEFINED
                        parts.push( stack.push( "undefined" ) );
                        ip++;
                        break;

                    case op.PUSH_NULL:          // PUSH_NULL
                        parts.push( stack.push( "null" ) );
                        ip++;
                        break;

                    case op.PUSH_FAILED:        // PUSH_FAILED
                        parts.push( stack.push( "peg$FAILED" ) );
                        ip++;
                        break;

                    case op.PUSH_EMPTY_ARRAY:   // PUSH_EMPTY_ARRAY
                        parts.push( stack.push( "[]" ) );
                        ip++;
                        break;

                    case op.POP:                // POP
                        stack.pop();
                        ip++;
                        break;

                    case op.POP_CURR_POS:       // POP_CURR_POS
                        parts.push( "peg$currPos = " + stack.pop() + ";" );
                        ip++;
                        break;

                    case op.POP_N:              // POP_N n
                        stack.pop( bc[ ip + 1 ] );
                        ip += 2;
                        break;

                    case op.NIP:                // NIP
                        value = stack.pop();
                        stack.pop();
                        parts.push( stack.push( value ) );
                        ip++;
                        break;

                    case op.APPEND:             // APPEND
                        value = stack.pop();
                        parts.push( stack.top() + ".push(" + value + ");" );
                        ip++;
                        break;

                    case op.WRAP:               // WRAP n
                        parts.push(
                            stack.push( "[" + stack.pop( bc[ ip + 1 ] ).join( ", " ) + "]" )
                        );
                        ip += 2;
                        break;

                    case op.TEXT:               // TEXT
                        parts.push(
                            stack.push( "input.substring(" + stack.pop() + ", peg$currPos)" )
                        );
                        ip++;
                        break;

                    case op.PLUCK:               // PLUCK n, k, p1, ..., pK
                        const baseLength = 3;
                        const paramsLength = bc[ ip + baseLength - 1 ];
                        const n = baseLength + paramsLength;
                        value = bc.slice( ip + baseLength, ip + n );
                        value = paramsLength === 1
                            ? stack.index( value[ 0 ] )
                            : `[ ${
                                value.map( p => stack.index( p ) )
                                    .join( ", " )
                            } ]`;
                        stack.pop( bc[ ip + 1 ] );
                        parts.push( stack.push( value ) );
                        ip += n;
                        break;

                    case op.IF:                 // IF t, f
                        compileCondition( stack.top(), 0 );
                        break;

                    case op.IF_ERROR:           // IF_ERROR t, f
                        compileCondition( stack.top() + " === peg$FAILED", 0 );
                        break;

                    case op.IF_NOT_ERROR:       // IF_NOT_ERROR t, f
                        compileCondition( stack.top() + " !== peg$FAILED", 0 );
                        break;

                    case op.WHILE_NOT_ERROR:    // WHILE_NOT_ERROR b
                        compileLoop( stack.top() + " !== peg$FAILED", 0 );
                        break;

                    case op.MATCH_ANY:          // MATCH_ANY a, f, ...
                        compileCondition( "input.length > peg$currPos", 0 );
                        break;

                    case op.MATCH_STRING:       // MATCH_STRING s, a, f, ...
                        compileCondition(
                            ast.literals[ bc[ ip + 1 ] ].length > 1
                                ? "input.substr(peg$currPos, "
                                    + ast.literals[ bc[ ip + 1 ] ].length
                                    + ") === "
                                    + l( bc[ ip + 1 ] )
                                : "input.charCodeAt(peg$currPos) === "
                                    + ast.literals[ bc[ ip + 1 ] ].charCodeAt( 0 )
                            , 1
                        );
                        break;

                    case op.MATCH_STRING_IC:    // MATCH_STRING_IC s, a, f, ...
                        compileCondition(
                            "input.substr(peg$currPos, "
                                + ast.literals[ bc[ ip + 1 ] ].length
                                + ").toLowerCase() === "
                                + l( bc[ ip + 1 ] )
                            , 1
                        );
                        break;

                    case op.MATCH_CLASS:        // MATCH_CLASS c, a, f, ...
                        compileCondition( r( bc[ ip + 1 ] ) + ".test(input.charAt(peg$currPos))", 1 );
                        break;

                    case op.ACCEPT_N:           // ACCEPT_N n
                        parts.push( stack.push(
                            bc[ ip + 1 ] > 1
                                ? "input.substr(peg$currPos, " + bc[ ip + 1 ] + ")"
                                : "input.charAt(peg$currPos)"
                        ) );
                        parts.push(
                            bc[ ip + 1 ] > 1
                                ? "peg$currPos += " + bc[ ip + 1 ] + ";"
                                : "peg$currPos++;"
                        );
                        ip += 2;
                        break;

                    case op.ACCEPT_STRING:      // ACCEPT_STRING s
                        parts.push( stack.push( l( bc[ ip + 1 ] ) ) );
                        parts.push(
                            ast.literals[ bc[ ip + 1 ] ].length > 1
                                ? "peg$currPos += " + ast.literals[ bc[ ip + 1 ] ].length + ";"
                                : "peg$currPos++;"
                        );
                        ip += 2;
                        break;

                    case op.EXPECT:             // EXPECT e
                        parts.push( "rule$expects(" + e( bc[ ip + 1 ] ) + ");" );
                        ip += 2;
                        break;

                    case op.LOAD_SAVED_POS:     // LOAD_SAVED_POS p
                        parts.push( "peg$savedPos = " + stack.index( bc[ ip + 1 ] ) + ";" );
                        ip += 2;
                        break;

                    case op.UPDATE_SAVED_POS:   // UPDATE_SAVED_POS
                        parts.push( "peg$savedPos = peg$currPos;" );
                        ip++;
                        break;

                    case op.CALL:               // CALL f, n, pc, p1, p2, ..., pN
                        compileCall();
                        break;

                    case op.RULE:               // RULE r
                        parts.push( stack.push( "peg$parse" + ast.rules[ bc[ ip + 1 ] ].name + "()" ) );
                        ip += 2;
                        break;

                    case op.SILENT_FAILS_ON:    // SILENT_FAILS_ON
                        parts.push( "peg$silentFails++;" );
                        ip++;
                        break;

                    case op.SILENT_FAILS_OFF:   // SILENT_FAILS_OFF
                        parts.push( "peg$silentFails--;" );
                        ip++;
                        break;

                    case op.EXPECT_NS_BEGIN:    // EXPECT_NS_BEGIN
                        parts.push( "peg$begin();" );
                        ip++;
                        break;

                    case op.EXPECT_NS_END:      // EXPECT_NS_END invert
                        parts.push( "peg$end(" + ( bc[ ip + 1 ] !== 0 ) + ");" );
                        ip += 2;
                        break;

                    // istanbul ignore next
                    default:
                        session.fatal(
                            "Rule '" + rule.name + "', position " + ip + ": "
                            + "Invalid opcode " + bc[ ip ] + "."
                        );

                }

            }

            return parts.join( "\n" );

        }

        const code = compile( rule.bytecode );

        parts.push( "function peg$parse" + rule.name + "() {" );

        if ( options.trace ) {

            parts.push( "  var startPos = peg$currPos;" );

        }

        for ( let i = 0; i <= stack.maxSp; i++ ) {

            stackVars[ i ] = s( i );

        }

        parts.push( "  var " + stackVars.join( ", " ) + ";" );

        parts.push( indent2( generateRuleHeader(
            "\"" + util.stringEscape( rule.name ) + "\"",
            ast.indexOfRule( rule.name )
        ) ) );
        parts.push( indent2( code ) );
        parts.push( indent2( generateRuleFooter(
            "\"" + util.stringEscape( rule.name ) + "\"",
            s( 0 )
        ) ) );

        parts.push( "}" );

        return parts.join( "\n" );

    }

    function generateToplevel() {

        const parts = [];

        parts.push( [
            "function peg$subclass(child, parent) {",
            "  function C() { this.constructor = child; }",
            "  C.prototype = parent.prototype;",
            "  child.prototype = new C();",
            "}",
            "",
            "function peg$SyntaxError(message, expected, found, location) {",
            "  this.message = message;",
            "  this.expected = expected;",
            "  this.found = found;",
            "  this.location = location;",
            "  this.name = \"SyntaxError\";",
            "",
            "  // istanbul ignore next",
            "  if (typeof Error.captureStackTrace === \"function\") {",
            "    Error.captureStackTrace(this, peg$SyntaxError);",
            "  }",
            "}",
            "",
            "peg$subclass(peg$SyntaxError, Error);",
            "",
            "peg$SyntaxError.buildMessage = function(expected, found) {",
            "  var DESCRIBE_EXPECTATION_FNS = {",
            "    literal: function(expectation) {",
            "      return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";",
            "    },",
            "",
            "    class: function(expectation) {",
            "      var escapedParts = expectation.parts.map(function(part) {",
            "        return Array.isArray(part)",
            "          ? classEscape(part[0]) + \"-\" + classEscape(part[1])",
            "          : classEscape(part);",
            "      });",
            "",
            "      return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";",
            "    },",
            "",
            "    any: function() {",
            "      return \"any character\";",
            "    },",
            "",
            "    end: function() {",
            "      return \"end of input\";",
            "    },",
            "",
            "    other: function(expectation) {",
            "      return expectation.description;",
            "    },",
            "",
            "    not: function(expectation) {",
            "      return \"not \" + describeExpectation(expectation.expected);",
            "    }",
            "  };",
            "",
            "  function hex(ch) {",
            "    return ch.charCodeAt(0).toString(16).toUpperCase();",
            "  }",
            "",
            "  function literalEscape(s) {",
            "    return s",
            "      .replace(/\\\\/g, \"\\\\\\\\\")",   // backslash
            "      .replace(/\"/g,  \"\\\\\\\"\")",    // closing double quote
            "      .replace(/\\0/g, \"\\\\0\")",       // null
            "      .replace(/\\t/g, \"\\\\t\")",       // horizontal tab
            "      .replace(/\\n/g, \"\\\\n\")",       // line feed
            "      .replace(/\\r/g, \"\\\\r\")",       // carriage return
            "      .replace(/[\\x00-\\x0F]/g,          function(ch) { return \"\\\\x0\" + hex(ch); })",
            "      .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \"\\\\x\"  + hex(ch); });",
            "  }",
            "",
            "  function classEscape(s) {",
            "    return s",
            "      .replace(/\\\\/g, \"\\\\\\\\\")",   // backslash
            "      .replace(/\\]/g, \"\\\\]\")",       // closing bracket
            "      .replace(/\\^/g, \"\\\\^\")",       // caret
            "      .replace(/-/g,  \"\\\\-\")",        // dash
            "      .replace(/\\0/g, \"\\\\0\")",       // null
            "      .replace(/\\t/g, \"\\\\t\")",       // horizontal tab
            "      .replace(/\\n/g, \"\\\\n\")",       // line feed
            "      .replace(/\\r/g, \"\\\\r\")",       // carriage return
            "      .replace(/[\\x00-\\x0F]/g,          function(ch) { return \"\\\\x0\" + hex(ch); })",
            "      .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, function(ch) { return \"\\\\x\"  + hex(ch); });",
            "  }",
            "",
            "  function describeExpectation(expectation) {",
            "    return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);",
            "  }",
            "",
            "  function describeExpected(expected) {",
            "    var descriptions = expected.map(describeExpectation);",
            "    var i, j;",
            "",
            "    descriptions.sort();",
            "",
            "    if (descriptions.length > 0) {",
            "      for (i = 1, j = 1; i < descriptions.length; i++) {",
            "        if (descriptions[i - 1] !== descriptions[i]) {",
            "          descriptions[j] = descriptions[i];",
            "          j++;",
            "        }",
            "      }",
            "      descriptions.length = j;",
            "    }",
            "",
            "    switch (descriptions.length) {",
            "      case 1:",
            "        return descriptions[0];",
            "",
            "      case 2:",
            "        return descriptions[0] + \" or \" + descriptions[1];",
            "",
            "      default:",
            "        return descriptions.slice(0, -1).join(\", \")",
            "          + \", or \"",
            "          + descriptions[descriptions.length - 1];",
            "    }",
            "  }",
            "",
            "  function describeFound(found) {",
            "    return found ? \"\\\"\" + literalEscape(found) + \"\\\"\" : \"end of input\";",
            "  }",
            "",
            "  return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";",
            "};",
            ""
        ].join( "\n" ) );

        if ( options.trace ) {

            if ( use( "DefaultTracer" ) )

                parts.push( [
                    "function peg$DefaultTracer() {",
                    "  this.indentLevel = 0;",
                    "}",
                    "",
                    "peg$DefaultTracer.prototype.trace = function(event) {",
                    "  var that = this;",
                    "",
                    "  function log(event) {",
                    "    function repeat(string, n) {",
                    "       var result = \"\", i;",
                    "",
                    "       for (i = 0; i < n; i++) {",
                    "         result += string;",
                    "       }",
                    "",
                    "       return result;",
                    "    }",
                    "",
                    "    function pad(string, length) {",
                    "      return string + repeat(\" \", length - string.length);",
                    "    }",
                    "",
                    "    if (typeof console === \"object\") {",   // IE 8-10
                    "      console.log(",
                    "        event.location.start.line + \":\" + event.location.start.column + \"-\"",
                    "          + event.location.end.line + \":\" + event.location.end.column + \" \"",
                    "          + pad(event.type, 10) + \" \"",
                    "          + repeat(\"  \", that.indentLevel) + event.rule",
                    "      );",
                    "    }",
                    "  }",
                    "",
                    "  switch (event.type) {",
                    "    case \"rule.enter\":",
                    "      log(event);",
                    "      this.indentLevel++;",
                    "      break;",
                    "",
                    "    case \"rule.match\":",
                    "      this.indentLevel--;",
                    "      log(event);",
                    "      break;",
                    "",
                    "    case \"rule.fail\":",
                    "      this.indentLevel--;",
                    "      log(event);",
                    "      break;",
                    "",
                    "    // istanbul ignore next",
                    "    default:",
                    "      throw new Error(\"Invalid event type: \" + event.type + \".\");",
                    "  }",
                    "};",
                    ""
                ].join( "\n" ) );

            else

                parts.push( [
                    "var peg$FauxTracer = {",
                    "  trace: function(event) { }",
                    "};",
                    ""
                ].join( "\n" ) );

        }

        parts.push( [
            "function peg$parse(input, options) {",
            "  options = options !== undefined ? options : {};",
            "",
            "  var peg$FAILED = {};",
            ""
        ].join( "\n" ) );

        if ( options.optimize === "size" ) {

            const startRuleIndices = "{ "
                + options.allowedStartRules
                    .map( r => r + ": " + ast.indexOfRule( r ) )
                    .join( ", " )
                + " }";
            const startRuleIndex = ast.indexOfRule( options.allowedStartRules[ 0 ] );

            parts.push( [
                "  var peg$startRuleIndices = " + startRuleIndices + ";",
                "  var peg$startRuleIndex = " + startRuleIndex + ";"
            ].join( "\n" ) );

        } else {

            const startRuleFunctions = "{ "
                + options.allowedStartRules
                    .map( r => r + ": peg$parse" + r )
                    .join( ", " )
                + " }";
            const startRuleFunction = "peg$parse" + options.allowedStartRules[ 0 ];

            parts.push( [
                "  var peg$startRuleFunctions = " + startRuleFunctions + ";",
                "  var peg$startRuleFunction = " + startRuleFunction + ";"
            ].join( "\n" ) );

        }

        parts.push( "" );

        parts.push( indent2( generateTables() ) );

        parts.push( [
            "",
            "  var peg$currPos = 0;",
            "  var peg$savedPos = 0;",
            "  var peg$posDetailsCache = [{ line: 1, column: 1 }];",
            "  var peg$expected = [];",
            "  var peg$silentFails = 0;",   // 0 = report failures, > 0 = silence failures
            ""
        ].join( "\n" ) );

        if ( options.cache ) {

            parts.push( [
                "  var peg$resultsCache = {};",
                ""
            ].join( "\n" ) );

        }

        if ( options.trace ) {

            if ( options.optimize === "size" ) {

                const ruleNames = "["
                    + ast.rules
                        .map( r => `"${ util.stringEscape( r.name ) }"` )
                        .join( ", " )
                    + "]";

                parts.push( [
                    "  var peg$ruleNames = " + ruleNames + ";",
                    ""
                ].join( "\n" ) );

            }

            if ( use( "DefaultTracer" ) )

                parts.push( [
                    "  var peg$tracer = \"tracer\" in options ? options.tracer : new peg$DefaultTracer();",
                    ""
                ].join( "\n" ) );

            else

                parts.push( [
                    "  var peg$tracer = \"tracer\" in options ? options.tracer : peg$FauxTracer;",
                    ""
                ].join( "\n" ) );

        }

        parts.push( [
            "  var peg$result;",
            ""
        ].join( "\n" ) );

        if ( options.optimize === "size" ) {

            parts.push( [
                "  if (\"startRule\" in options) {",
                "    if (!(options.startRule in peg$startRuleIndices)) {",
                "      throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");",
                "    }",
                "",
                "    peg$startRuleIndex = peg$startRuleIndices[options.startRule];",
                "  }"
            ].join( "\n" ) );

        } else {

            parts.push( [
                "  if (\"startRule\" in options) {",
                "    if (!(options.startRule in peg$startRuleFunctions)) {",
                "      throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");",
                "    }",
                "",
                "    peg$startRuleFunction = peg$startRuleFunctions[options.startRule];",
                "  }"
            ].join( "\n" ) );

        }

        if ( use( "text" ) ) {

            parts.push( [
                "",
                "  function text() {",
                "    return input.substring(peg$savedPos, peg$currPos);",
                "  }",
            ].join( "\n" ) );

        }

        if ( use( "offset" ) ) {

            parts.push( [
                "",
                "  function offset() {",
                "    return peg$savedPos;",
                "  }",
            ].join( "\n" ) );

        }

        if ( use( "range" ) ) {

            parts.push( [
                "",
                "  function range() {",
                "    return [peg$savedPos, peg$currPos];",
                "  }",
            ].join( "\n" ) );

        }

        if ( use( "location" ) ) {

            parts.push( [
                "",
                "  function location() {",
                "    return peg$computeLocation(peg$savedPos, peg$currPos);",
                "  }",
            ].join( "\n" ) );

        }

        if ( use( "expected" ) ) {

            parts.push( [
                "",
                "  function expected(description, location) {",
                "    location = location !== undefined",
                "      ? location",
                "      : peg$computeLocation(peg$savedPos, peg$currPos);",
                "",
                "    throw peg$buildStructuredError(",
                "      [peg$otherExpectation(description)],",
                "      input.substring(peg$savedPos, peg$currPos),",
                "      location",
                "    );",
                "  }",
            ].join( "\n" ) );

        }

        if ( use( "error" ) ) {

            parts.push( [
                "",
                "  function error(message, location) {",
                "    location = location !== undefined",
                "      ? location",
                "      : peg$computeLocation(peg$savedPos, peg$currPos);",
                "",
                "    throw peg$buildSimpleError(message, location);",
                "  }",
            ].join( "\n" ) );

        }

        parts.push( [
            "",
            "  function peg$literalExpectation(text, ignoreCase) {",
            "    return { type: \"literal\", text: text, ignoreCase: ignoreCase };",
            "  }",
            "",
            "  function peg$classExpectation(parts, inverted, ignoreCase) {",
            "    return { type: \"class\", parts: parts, inverted: inverted, ignoreCase: ignoreCase };",
            "  }",
            "",
            "  function peg$anyExpectation() {",
            "    return { type: \"any\" };",
            "  }",
            "",
            "  function peg$endExpectation() {",
            "    return { type: \"end\" };",
            "  }",
            "",
            "  function peg$otherExpectation(description) {",
            "    return { type: \"other\", description: description };",
            "  }",
            "",
            "  function peg$computePosDetails(pos) {",
            "    var details = peg$posDetailsCache[pos];",
            "    var p;",
            "",
            "    if (details) {",
            "      return details;",
            "    } else {",
            "      p = pos - 1;",
            "      while (!peg$posDetailsCache[p]) {",
            "        p--;",
            "      }",
            "",
            "      details = peg$posDetailsCache[p];",
            "      details = {",
            "        line: details.line,",
            "        column: details.column",
            "      };",
            "",
            "      while (p < pos) {",
            "        if (input.charCodeAt(p) === 10) {",
            "          details.line++;",
            "          details.column = 1;",
            "        } else {",
            "          details.column++;",
            "        }",
            "",
            "        p++;",
            "      }",
            "",
            "      peg$posDetailsCache[pos] = details;",
            "",
            "      return details;",
            "    }",
            "  }",
            "",
            use( "filename" ) ? "  var peg$VALIDFILENAME = typeof options.filename === \"string\" && options.filename.length > 0;" : "",
            "  function peg$computeLocation(startPos, endPos) {",
            "    var loc = {};",
            "",
            use( "filename" ) ? "    if ( peg$VALIDFILENAME ) loc.filename = options.filename;" : "",
            "",
            "    var startPosDetails = peg$computePosDetails(startPos);",
            "    loc.start = {",
            "      offset: startPos,",
            "      line: startPosDetails.line,",
            "      column: startPosDetails.column",
            "    };",
            "",
            "    var endPosDetails = peg$computePosDetails(endPos);",
            "    loc.end = {",
            "      offset: endPos,",
            "      line: endPosDetails.line,",
            "      column: endPosDetails.column",
            "    };",
            "",
            "    return loc;",
            "  }",
            "",
            "  function peg$begin() {",
            "    peg$expected.push({ pos: peg$currPos, variants: [] });",
            "  }",
            "",
            "  function peg$expect(expected) {",
            "    var top = peg$expected[peg$expected.length - 1];",
            "",
            "    if (peg$currPos < top.pos) { return; }",
            "",
            "    if (peg$currPos > top.pos) {",
            "      top.pos = peg$currPos;",
            "      top.variants = [];",
            "    }",
            "",
            "    top.variants.push(expected);",
            "  }",
            "",
            "  function peg$end(invert) {",
            "    var expected = peg$expected.pop();",
            "    var top = peg$expected[peg$expected.length - 1];",
            "    var variants = expected.variants;",
            "",
            "    if (top.pos !== expected.pos) { return; }",
            "",
            "    if (invert) {",
            "      variants = variants.map(function(e) {",
            "        return e.type === \"not\" ? e.expected : { type: \"not\", expected: e };",
            "      });",
            "    }",
            "",
            "    Array.prototype.push.apply(top.variants, variants);",
            "  }",
            "",
            "  function peg$buildSimpleError(message, location) {",
            "    return new peg$SyntaxError(message, null, null, location);",
            "  }",
            "",
            "  function peg$buildStructuredError(expected, found, location) {",
            "    return new peg$SyntaxError(",
            "      peg$SyntaxError.buildMessage(expected, found),",
            "      expected,",
            "      found,",
            "      location",
            "    );",
            "  }",
            "",
            "  function peg$buildError() {",
            "    var expected = peg$expected[0];",
            "    var failPos = expected.pos;",
            "",
            "    return peg$buildStructuredError(",
            "      expected.variants,",
            "      failPos < input.length ? input.charAt(failPos) : null,",
            "      failPos < input.length",
            "        ? peg$computeLocation(failPos, failPos + 1)",
            "        : peg$computeLocation(failPos, failPos)",
            "    );",
            "  }",
            ""
        ].join( "\n" ) );

        if ( options.optimize === "size" ) {

            parts.push( indent2( generateInterpreter() ) );
            parts.push( "" );

        } else {

            ast.rules.forEach( rule => {

                parts.push( indent2( generateRuleFunction( rule ) ) );
                parts.push( "" );

            } );

        }

        if ( ast.initializer ) {

            parts.push( indent2( ast.initializer.code ) );
            parts.push( "" );

        }

        parts.push( "  peg$begin();" );

        if ( options.optimize === "size" ) {

            parts.push( "  peg$result = peg$parseRule(peg$startRuleIndex);" );

        } else {

            parts.push( "  peg$result = peg$startRuleFunction();" );

        }

        parts.push( [
            "",
            "  if (peg$result !== peg$FAILED && peg$currPos === input.length) {",
            "    return peg$result;",
            "  } else {",
            "    if (peg$result !== peg$FAILED && peg$currPos < input.length) {",
            "      peg$expect(peg$endExpectation());",
            "    }",
            "",
            "    throw peg$buildError();",
            "  }",
            "}"
        ].join( "\n" ) );

        return parts.join( "\n" );

    }

    function generateWrapper( toplevelCode ) {

        function generateHeaderComment() {

            let comment = `// Generated by PEG.js v${ VERSION }, https://pegjs.org/`;
            const header = options.header;

            if ( typeof header === "string" ) {

                comment += "\n\n" + header;

            } else if ( Array.isArray( header ) ) {

                comment += "\n\n";
                header.forEach( data => {

                    comment += "// " + data;

                } );

            }

            return comment;

        }

        function generateParserObject() {

            return options.trace && use( "DefaultTracer" )
                ? [
                    "{",
                    "  SyntaxError: peg$SyntaxError,",
                    "  DefaultTracer: peg$DefaultTracer,",
                    "  parse: peg$parse",
                    "}"
                ].join( "\n" )
                : [
                    "{",
                    "  SyntaxError: peg$SyntaxError,",
                    "  parse: peg$parse",
                    "}"
                ].join( "\n" );

        }

        function generateParserExports() {

            return options.trace && use( "DefaultTracer" )
                ? [
                    "{",
                    "  peg$SyntaxError as SyntaxError,",
                    "  peg$DefaultTracer as DefaultTracer,",
                    "  peg$parse as parse",
                    "}"
                ].join( "\n" )
                : [
                    "{",
                    "  peg$SyntaxError as SyntaxError,",
                    "  peg$parse as parse",
                    "}"
                ].join( "\n" );

        }

        const generators = {
            bare() {

                return [
                    generateHeaderComment(),
                    "(function() {",
                    "  \"use strict\";",
                    "",
                    indent2( toplevelCode ),
                    "",
                    indent2( "return " + generateParserObject() + ";" ),
                    "})()"
                ].join( "\n" );

            },

            commonjs() {

                const parts = [];
                const dependencyVars = Object.keys( options.dependencies );

                parts.push( [
                    generateHeaderComment(),
                    "",
                    "\"use strict\";",
                    ""
                ].join( "\n" ) );

                if ( dependencyVars.length > 0 ) {

                    dependencyVars.forEach( variable => {

                        parts.push( "var " + variable
                            + " = require(\""
                            + util.stringEscape( options.dependencies[ variable ] )
                            + "\");"
                        );

                    } );
                    parts.push( "" );

                }

                parts.push( [
                    toplevelCode,
                    "",
                    "module.exports = " + generateParserObject() + ";",
                    ""
                ].join( "\n" ) );

                return parts.join( "\n" );

            },

            es() {

                const parts = [];
                const dependencyVars = Object.keys( options.dependencies );

                parts.push(
                    generateHeaderComment(),
                    ""
                );

                if ( dependencyVars.length > 0 ) {

                    dependencyVars.forEach( variable => {

                        parts.push( "import " + variable
                            + " from \""
                            + util.stringEscape( options.dependencies[ variable ] )
                            + "\";"
                        );

                    } );
                    parts.push( "" );

                }

                parts.push(
                    toplevelCode,
                    "",
                    "export " + generateParserExports() + ";",
                    "",
                    "export default " + generateParserObject() + ";",
                    ""
                );

                return parts.join( "\n" );

            },

            amd() {

                const dependencyVars = Object.keys( options.dependencies );
                const dependencyIds = dependencyVars.map( v => options.dependencies[ v ] );
                const dependencies = "["
                    + dependencyIds
                        .map( id => `"${ util.stringEscape( id ) }"` )
                        .join( ", " )
                    + "]";
                const params = dependencyVars.join( ", " );

                return [
                    generateHeaderComment(),
                    "define(" + dependencies + ", function(" + params + ") {",
                    "  \"use strict\";",
                    "",
                    indent2( toplevelCode ),
                    "",
                    indent2( "return " + generateParserObject() + ";" ),
                    "});",
                    ""
                ].join( "\n" );

            },

            globals() {

                return [
                    generateHeaderComment(),
                    "(function(root) {",
                    "  \"use strict\";",
                    "",
                    indent2( toplevelCode ),
                    "",
                    indent2( "root." + options.exportVar + " = " + generateParserObject() + ";" ),
                    "})(this);",
                    ""
                ].join( "\n" );

            },

            umd() {

                const parts = [];
                const dependencyVars = Object.keys( options.dependencies );
                const dependencyIds = dependencyVars.map( v => options.dependencies[ v ] );
                const dependencies = "["
                    + dependencyIds
                        .map( id => `"${ util.stringEscape( id ) }"` )
                        .join( ", " )
                    + "]";
                const requires = dependencyIds
                    .map( id => `require("${ util.stringEscape( id ) }")` )
                    .join( ", " );
                const args = dependencyVars.map( v => "root." + v ).join( ", " );
                const params = dependencyVars.join( ", " );

                parts.push( [
                    generateHeaderComment(),
                    "(function(root, factory) {",
                    "  if (typeof define === \"function\" && define.amd) {",
                    "    define(" + dependencies + ", factory);",
                    "  } else if (typeof module === \"object\" && module.exports) {",
                    "    module.exports = factory(" + requires + ");"
                ].join( "\n" ) );

                if ( options.exportVar !== null ) {

                    parts.push( [
                        "  } else {",
                        "    root." + options.exportVar + " = factory(" + args + ");"
                    ].join( "\n" ) );

                }

                parts.push( [
                    "  }",
                    "})(this, function(" + params + ") {",
                    "  \"use strict\";",
                    "",
                    indent2( toplevelCode ),
                    "",
                    indent2( "return " + generateParserObject() + ";" ),
                    "});",
                    ""
                ].join( "\n" ) );

                return parts.join( "\n" );

            }
        };

        return generators[ options.format ]();

    }

    ast.code = generateWrapper( generateToplevel() );

}
512122
private boolean props(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type, String tag, String value) {
		boolean rv = false;
		if(type.y!=null) {
			for(Pair<String,Object> prop : type.y.y){
				if(tag.equals(prop.x)) {
					if(tag.equals("charset")) {
						return prop.x==null?false:prop.y.equals(value.toLowerCase()); // return True if Matched
					} else if(tag.equals("version")) {
						return prop.y.equals(new Version(value)); // Note: Version Class knows Minor Version encoding
					} else if(tag.equals(Content.Q)) { // replace Q value
						try {
							type.y.y.get(0).y=Float.parseFloat(value);
						} catch (NumberFormatException e) {
							rv=false; // need to do something to make Sonar happy. But nothing to do.
						}
						return true;
					} else {
						return value.equals(prop.y);
					}
				}
			}
		}
		return rv;
	}
929548
function parseStyles(s) {
  var parser = new parserlib.css.Parser();
  var result = { property: Object.create(null), priority: Object.create(null) };
  parser.addListener("property", function(e) {
    if (e.invalid) return; // Skip errors
    result.property[e.property.text] = e.value.text;
    if (e.important) result.priority[e.property.text] = 'important';
  });
  s = (''+s).replace(/^;/, '');
  parser.parseStyleAttribute(s);
  return result;
}
629558
function(val, cx, partials, text, tags) {
      var compiler = this.c;
      var options = this.options;
      options.delimiters = tags;
      var t = val.call(cx, text, function(t) {
        return compiler.compile(t, options).render(cx, partials);
      });
      this.b(compiler.compile(t.toString(), options).render(cx, partials));
      return false;
    }
288056
function ast (tokens) {
  let token = tokens[0]

  const state = {
    content: []
  }

  let current = state
  let active = current
  const stack = []
  let lineStackSize = 0 // when inline entities are used this gets incremented so that when you
  // go onto a new line we can go back to the correct location in the stack

  const l = tokens.length
  let i = 0
  let absoluteIndent = 0
  let currentIndent = 0
  let extraIndent = 0
  let prevWasType = false
  let nextParamsAreEscaped = false
  let prevParamsWereEscaped = false
  const emptyLines = []
  let handlingInlineContent = false // true when between an START_INLINE_CONTENT and END_INLINE_CONTENT
  /*
    notCreatedInlineContent
    This is true when the inline content entry has not yet been created in the parsed
    content (which is done for the first content encountered between START_INLINE_CONTENT
    and END_INLINE_CONTENT)
  */
  let notCreatedInlineContent = true

  while (i < l) {
    token = tokens[i]
    if (token.type === 'TYPE') {
      if (token.value === '') {
        nextParamsAreEscaped = true
      } else {
        prevWasType = true

        active = {
          type: token.value,
          params: [],
          content: []
        }

        while (emptyLines.length) {
          current.content.push(emptyLines.pop())
        }

        current.content.push(active)
      }
    } else if (token.type === 'PARAMS') {
      if (nextParamsAreEscaped) {
        if (active.content.length > 0) {
          active.content[active.content.length - 1] += token.value
        } else {
          active.content.push(token.value)
        }
        nextParamsAreEscaped = false
        prevParamsWereEscaped = true
      } else {
        active.params = splitParams(token.value)
      }
    } else if (token.type === 'CONTENT') {
      if (prevParamsWereEscaped) {
        active.content[active.content.length - 1] += token.value
        prevParamsWereEscaped = false
      } else if (token.value === '') {
        emptyLines.push(token.value)
      } else {
        while (emptyLines.length) {
          current.content.push(emptyLines.pop())
        }

        prevWasType = false

        if (handlingInlineContent) {
          if (notCreatedInlineContent) {
            current.content.push(token.value)
            notCreatedInlineContent = false
          } else {
            current.content[current.content.length - 1] += ' ' + token.value
          }
        } else {
          let ex = ''
          for (let k = 0; k < extraIndent; k++) {
            ex += ' '
          }
          current.content.push(ex + token.value)
        }
      }
    } else if (token.type === 'EMPTY_CONTENT') {
      emptyLines.push(token.value)
    } else if (token.type === 'START_SAME_LINE_CONTENT') {
      lineStackSize++
      stack.push(current)
      current = active
    } else if (token.type === 'END_SAME_LINE_CONTENT') {
      // keep the active as it is, even though the current is being droped back a couple of levels
      // this is so that you can do @one: @two: @three\n @four, and have @four be a child of @three (not @one)
      active = current

      // drop back down the stack until you reach where we were at the start of the line
      while (lineStackSize) {
        current = stack.pop()
        lineStackSize--
      }
      prevWasType = true
    } else if (token.type === 'START_INLINE_CONTENT') {
      handlingInlineContent = true
      notCreatedInlineContent = true
      lineStackSize++
      stack.push(current)
      current = active
    } else if (token.type === 'END_INLINE_CONTENT') {
      handlingInlineContent = false
      active = current
      current = stack.pop()
      lineStackSize--
      prevWasType = true
    } else if (token.type === 'INDENT') {
      stack.push(current)
      current = active
      absoluteIndent += token.value

      if (prevWasType) {
        currentIndent = absoluteIndent
      }

      extraIndent = absoluteIndent - currentIndent
    } else if (token.type === 'DEDENT') {
      current = stack.pop()
      active = current
      absoluteIndent -= token.value

      if (extraIndent > 0) {
        extraIndent -= token.value
      } else {
        currentIndent = absoluteIndent
      }
    }
    i++
  }

  return state.content
}
563216
function buildElementTag( def, code, varName ) {
    const attribs = extractAttribs( def );

    try {
        const arr = Object.keys( attribs.standard );
        code.requires[ "Tag" ] = "require('tfw.view').Tag";
        code.section.elements.define.push(
            "const " + varName + " = new Tag('" + def[ 0 ] + "'" +
            ( arr.length > 0 ? ', ' + JSON.stringify( arr ) : '' ) +
            ");" );

        const initAttribs = buildElementTagAttribsStandard( attribs.standard, code, varName );
        buildInitAttribsForTag( initAttribs, code, varName );
        buildElementEvents( attribs.special, code, varName );
        buildElementTagClassSwitcher( attribs.special, code, varName );
        buildElementTagAttribSwitcher( attribs.special, code, varName );
        buildElementTagStyle( attribs.special, code, varName );
        buildElementTagChildren( attribs.special, code, varName );
        buildElementTagOn( attribs.special, code, varName );
    } catch ( ex ) {
        throw ex + "\n...in tag \"" + varName + "\": " + limitJson( def );
    }
}
1102688
@Override
  protected void visitLetValueNode(LetValueNode node) {

    String generatedVarName = node.getUniqueVarName();

    // Generate code to define the local var.
    Expression value = translateExpr(node.getExpr());
    jsCodeBuilder.append(VariableDeclaration.builder(generatedVarName).setRhs(value).build());

    // Add a mapping for generating future references to this local var.
    templateTranslationContext
        .soyToJsVariableMappings()
        .put(node.getVarName(), id(generatedVarName));
  }
1058072
function generateTheme({
  stylesDir,
  mainLessFile,
  varFile,
  outputFilePath,
  themeVariables
}) {
  return new Promise((resolve, reject) => {
    /*
      You own custom styles (Change according to your project structure)
      
      - stylesDir - styles directory containing all less files
      - varFile - variable file containing your custom variables
      - mainLessFile - less main file which imports all styles
    */
    let content = '';
    // const hashCode = hash.sha256().update(content).digest('hex');
    // if(hashCode === hashCache){
    //   resolve(cssCache);
    //   return;
    // }
    // hashCache = hashCode;
    let themeCompiledVars = {};
    let themeVars = themeVariables || [];
    const lessPaths = [
      stylesDir
    ];

    return bundle({
      src: varFile
    })
      .then(colorsLess => {
        const mappings = Object.assign(generateColorMap(colorsLess), mainLessFile? generateColorMap(mainLessFile): {});
        return [mappings, colorsLess];
      })
      .then(([mappings, colorsLess]) => {
        let css = "";
        /*
         If not pass in themeVariables, the variables in varFile will be used
         */
        if (!themeVariables) {
            let varJs = lessToJs(fs.readFileSync(varFile, 'utf8'));
            themeVars.forEach(varName => {
                delete varJs[varName];
            });
            themeVars.push(...Object.keys(varJs));
        }
        if (!themeVars.length) {
            themeVars.push("@theme-color");
        }
        themeVars = themeVars.filter(name => name in mappings);
        themeVars.forEach(varName => {
          const color = mappings[varName];
          css = `.${varName.replace("@", "")} { color: ${color}; }\n ${css}`;
        });

        css = `${colorsLess}\n${css}`;
        return render(css, lessPaths).then(({ css }) => [
          css,
          mappings,
          colorsLess
        ]);
      })
      .then(([css, mappings, colorsLess]) => {
        css = css.replace(/(\/.*\/)/g, "");
        const regex = /.(?=\S*['-])([.a-zA-Z0-9'-]+)\ {\n\ \ color:\ (.*);/g;
        themeCompiledVars = getMatches(css, regex);
        content = `${content}\n${colorsLess}`;
        return render(content, lessPaths).then(({ css }) => {
          return getCssModulesStyles(stylesDir).then(customCss => {
            return [
              `${customCss}\n${css}`,
              mappings,
              colorsLess
            ];
          })
          
        });
      })
      .then(([css, mappings, colorsLess]) => {
        return postcss([reducePlugin(themeCompiledVars)])
          .process(css, {
            parser: less.parser,
            from: mainLessFile | varFile
          })
          .then(({ css }) => [css, mappings, colorsLess]);
      })
      .then(([css, mappings, colorsLess]) => {
        Object.keys(themeCompiledVars).forEach(varName => {
          let color;
          if (/(.*)-(\d)/.test(varName)) {
            color = themeCompiledVars[varName];
            varName = getShade(varName);
          } else {
            color = themeCompiledVars[varName];
          }
          color = color.replace('(', '\\(').replace(')', '\\)');
          css = css.replace(new RegExp(`${color}`, "g"), varName);
        });

        css = `${colorsLess}\n${css}`;

        themeVars.reverse().forEach(varName => {
          css = css.replace(new RegExp(`${varName}(\ *):(.*);`, 'g'), '');
          css = `${varName}: ${mappings[varName]};\n${css}\n`;
        });
        css = css.replace(/\n+/g, '\n');

        css = uniqueCss(css);

        if (outputFilePath) {
          fs.writeFileSync(outputFilePath, css);
          console.log(
            `Theme generated successfully. OutputFile: ${outputFilePath}`
          );
        } else {
          console.log(`Theme generated successfully`);
        }
        cssCache = css;
        return resolve(css);
      })
      .catch(err => {
        console.log("Error", err);
        reject(err);
      });
  });
}
552782
function generateSubstitution(token, substitutionPattern, substitutions) {
  var substitution = substitutionPattern.replace(/{([^}]+)}/ig, (all, group)=> {
    switch (group) {
      case 'namespace':
        return token.namespace;
      case 'name':
        return token.className;
      case 'random':
        return 'r' + Math.random().toString(36).substring(7);
      case 'hash':
        return 'h' + (token.hash + 0.0).toString(36);
      case 'unique':
        return 'u' + (++uniqueCounter);
    }
  });

  substitutions[token.className] = [];
  substitutions[token.className].push(substitution);
  return substitution;
}
218909
function generateTables() {

        function buildLiteral( literal ) {

            return `"${ util.stringEscape( literal ) }"`;

        }

        function buildRegexp( cls ) {

            return "/^["
                + ( cls.inverted ? "^" : "" )
                + cls.value
                    .map( part => (

                        Array.isArray( part )
                            ? util.regexpEscape( part[ 0 ] )
                                + "-"
                                + util.regexpEscape( part[ 1 ] )
                            : util.regexpEscape( part )

                    ) )
                    .join( "" )
                + "]/"
                + ( cls.ignoreCase ? "i" : "" );

        }

        function buildExpectation( e ) {

            switch ( e.type ) {

                case "rule":
                    return `peg$otherExpectation("${ util.stringEscape( e.value ) }")`;

                case "literal":
                    return "peg$literalExpectation(\""
                           + util.stringEscape( e.value )
                           + "\", "
                           + e.ignoreCase
                           + ")";

                case "class": {

                    const parts = e.value.map( part =>
                        ( Array.isArray( part )
                            ? `["${ util.stringEscape( part[ 0 ] ) }", "${ util.stringEscape( part[ 1 ] ) }"]`
                            : `"${ util.stringEscape( part ) }"` )
                    );

                    return "peg$classExpectation(["
                           + parts.join( ", " ) + "], "
                           + e.inverted + ", "
                           + e.ignoreCase
                           + ")";

                }

                case "any":
                    return "peg$anyExpectation()";

                // istanbul ignore next
                default:
                    session.fatal( `Unknown expectation type (${ JSON.stringify( e ) })` );

            }

        }

        function buildFunc( f ) {

            return `function(${ f.params.join( ", " ) }) {${ f.body }}`;

        }

        if ( options.optimize === "size" ) {

            return [
                "var peg$literals = [",
                indent2( ast.literals.map( buildLiteral ).join( ",\n" ) ),
                "];",
                "var peg$regexps = [",
                indent2( ast.classes.map( buildRegexp ).join( ",\n" ) ),
                "];",
                "var peg$expectations = [",
                indent2( ast.expectations.map( buildExpectation ).join( ",\n" ) ),
                "];",
                "var peg$functions = [",
                indent2( ast.functions.map( buildFunc ).join( ",\n" ) ),
                "];",
                "",
                "var peg$bytecode = [",
                indent2( ast.rules
                    .map( rule =>
                        `peg$decode("${
                            util.stringEscape( rule.bytecode
                                .map( b => String.fromCharCode( b + 32 ) )
                                .join( "" )
                            )
                        }")`
                    )
                    .join( ",\n" )
                ),
                "];"
            ].join( "\n" );

        }

        return ast.literals
            .map( ( c, i ) => "var " + l( i ) + " = " + buildLiteral( c ) + ";" )
            .concat( "", ast.classes.map(
                ( c, i ) => "var " + r( i ) + " = " + buildRegexp( c ) + ";"
            ) )
            .concat( "", ast.expectations.map(
                ( c, i ) => "var " + e( i ) + " = " + buildExpectation( c ) + ";"
            ) )
            .concat( "", ast.functions.map(
                ( c, i ) => "var " + f( i ) + " = " + buildFunc( c ) + ";"
            ) )
            .join( "\n" );

    }
820884
private void generateProperties(JsonNode node, String parentPrefix,
			Properties props) {

		Iterator<Entry<String, JsonNode>> fields = node.fields();
		while (fields.hasNext()) {
			Entry<String, JsonNode> entry = fields.next();
			String fieldName = entry.getKey();
			JsonNode jsonNode = entry.getValue();
			String nodePrefix = parentPrefix == null ? fieldName : parentPrefix
					+ FIELD_NAME_SEPARATOR + fieldName;
			if (jsonNode.isTextual() || jsonNode.isBoolean()) {
				props.put(nodePrefix, jsonNode.asText());
			} else if (jsonNode.isNumber()) {
				props.put(nodePrefix, Integer.toString(jsonNode.asInt()));
			} else if (jsonNode.isArray()) {
				String arrayValue = convertToString(jsonNode);
				props.put(nodePrefix, arrayValue);
			}
			generateProperties(jsonNode, nodePrefix, props);
		}
	}
505111
function GENERATE_VAR(name, spec, parent) {
  return GENERATE_DOC(spec.description + '\n'
    + '@property ' + name + '\n'
    + '@type ' + spec.type + '\n'
    + '@for ' + parent + '\n');
}
484659
function generateTS(ast, options) {
  // These only indent non-empty lines to avoid trailing whitespace.
  function indent2(code) {
    return code.replace(/^(.+)$/gm, "  $1");
  }

  function indent10(code) {
    return code.replace(/^(.+)$/gm, "          $1");
  }

  function generateTables() {
    if (options.optimize === "size") {
      return [
        "const peg$consts = [",
        indent2(ast.consts.join(",\n")),
        "];",
        "",
        "const peg$bytecode = [",
        indent2(ast.rules.map(rule =>
          "peg$decode(\"" +
          js.stringEscape(rule.bytecode.map(
            b => String.fromCharCode(b + 32)
          ).join("")) +
          "\")"
        ).join(",\n")),
        "];"
      ].join("\n");
    } else {
      return ast.consts.map((c, i) => "const peg$c" + i + " = " + c + ";").join("\n");
    }
  }

  function generateRuleHeader(ruleNameCode, ruleIndexCode) {
    let parts = [];

    parts.push("");

    if (options.trace) {
      parts.push([
        "peg$tracer.trace({",
        "  type: \"rule.enter\",",
        "  rule: " + ruleNameCode + ",",
        "  location: peg$computeLocation(startPos, startPos)",
        "});",
        ""
      ].join("\n"));
    }

    if (options.cache) {
      parts.push([
        "const key = peg$currPos * " + ast.rules.length + " + " + ruleIndexCode + ";",
        "const cached: ICached = peg$resultsCache[key];",
        "",
        "if (cached) {",
        "  peg$currPos = cached.nextPos;",
        ""
      ].join("\n"));

      if (options.trace) {
        parts.push([
          "if (cached.result !== peg$FAILED) {",
          "  peg$tracer.trace({",
          "    type: \"rule.match\",",
          "    rule: " + ruleNameCode + ",",
          "    result: cached.result,",
          "    location: peg$computeLocation(startPos, peg$currPos)",
          "  });",
          "} else {",
          "  peg$tracer.trace({",
          "    type: \"rule.fail\",",
          "    rule: " + ruleNameCode + ",",
          "    location: peg$computeLocation(startPos, startPos)",
          "  });",
          "}",
          ""
        ].join("\n"));
      }

      parts.push([
        "  return cached.result;",
        "}",
        ""
      ].join("\n"));
    }

    return parts.join("\n");
  }

  function generateRuleFooter(ruleNameCode, resultCode) {
    let parts = [];

    if (options.cache) {
      parts.push([
        "",
        "peg$resultsCache[key] = { nextPos: peg$currPos, result: " + resultCode + " };"
      ].join("\n"));
    }

    if (options.trace) {
      parts.push([
        "",
        "if (" + resultCode + " !== peg$FAILED) {",
        "  peg$tracer.trace({",
        "    type: \"rule.match\",",
        "    rule: " + ruleNameCode + ",",
        "    result: " + resultCode + ",",
        "    location: peg$computeLocation(startPos, peg$currPos)",
        "  });",
        "} else {",
        "  peg$tracer.trace({",
        "    type: \"rule.fail\",",
        "    rule: " + ruleNameCode + ",",
        "    location: peg$computeLocation(startPos, startPos)",
        "  });",
        "}"
      ].join("\n"));
    }

    parts.push([
      "",
      "return " + resultCode + ";"
    ].join("\n"));

    return parts.join("\n");
  }

  function generateInterpreter() {
    let parts = [];

    function generateCondition(cond, argsLength) {
      let baseLength = argsLength + 3;
      let thenLengthCode = "bc[ip + " + (baseLength - 2) + "]";
      let elseLengthCode = "bc[ip + " + (baseLength - 1) + "]";

      return [
        "ends.push(end);",
        "ips.push(ip + " + baseLength + " + " + thenLengthCode + " + " + elseLengthCode + ");",
        "",
        "if (" + cond + ") {",
        "  end = ip + " + baseLength + " + " + thenLengthCode + ";",
        "  ip += " + baseLength + ";",
        "} else {",
        "  end = ip + " + baseLength + " + " + thenLengthCode + " + " + elseLengthCode + ";",
        "  ip += " + baseLength + " + " + thenLengthCode + ";",
        "}",
        "",
        "break;"
      ].join("\n");
    }

    function generateLoop(cond) {
      let baseLength = 2;
      let bodyLengthCode = "bc[ip + " + (baseLength - 1) + "]";

      return [
        "if (" + cond + ") {",
        "  ends.push(end);",
        "  ips.push(ip);",
        "",
        "  end = ip + " + baseLength + " + " + bodyLengthCode + ";",
        "  ip += " + baseLength + ";",
        "} else {",
        "  ip += " + baseLength + " + " + bodyLengthCode + ";",
        "}",
        "",
        "break;"
      ].join("\n");
    }

    function generateCall() {
      let baseLength = 4;
      let paramsLengthCode = "bc[ip + " + (baseLength - 1) + "]";

      return [
        "params = bc.slice(ip + " + baseLength + ", ip + " + baseLength + " + " + paramsLengthCode + ")",
        "  .map(function(p) { return stack[stack.length - 1 - p]; });",
        "",
        "stack.splice(",
        "  stack.length - bc[ip + 2],",
        "  bc[ip + 2],",
        "  peg$consts[bc[ip + 1]].apply(null, params)",
        ");",
        "",
        "ip += " + baseLength + " + " + paramsLengthCode + ";",
        "break;"
      ].join("\n");
    }

    parts.push([
      "function peg$decode(s: string): number {",
      "  return s.split(\"\").map((ch) => { return ch.charCodeAt(0) - 32; });",
      "}",
      "",
      "function peg$parseRule(index) {"
    ].join("\n"));

    if (options.trace) {
      parts.push([
        "  let bc = peg$bytecode[index];",
        "  let ip = 0;",
        "  let ips = [];",
        "  let end = bc.length;",
        "  let ends = [];",
        "  let stack = [];",
        "  let startPos = peg$currPos;",
        "  let params;"
      ].join("\n"));
    } else {
      parts.push([
        "  let bc = peg$bytecode[index];",
        "  let ip = 0;",
        "  let ips = [];",
        "  let end = bc.length;",
        "  let ends = [];",
        "  let stack = [];",
        "  let params;"
      ].join("\n"));
    }

    parts.push(indent2(generateRuleHeader("peg$ruleNames[index]", "index")));

    parts.push([
      // The point of the outer loop and the |ips| & |ends| stacks is to avoid
      // recursive calls for interpreting parts of bytecode. In other words, we
      // implement the |interpret| operation of the abstract machine without
      // function calls. Such calls would likely slow the parser down and more
      // importantly cause stack overflows for complex grammars.
      "  while (true) {",
      "    while (ip < end) {",
      "      switch (bc[ip]) {",
      "        case " + op.PUSH + ":", // PUSH c
      "          stack.push(peg$consts[bc[ip + 1]]);",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.PUSH_UNDEFINED + ":", // PUSH_UNDEFINED
      "          stack.push(undefined);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.PUSH_NULL + ":", // PUSH_NULL
      "          stack.push(null);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.PUSH_FAILED + ":", // PUSH_FAILED
      "          stack.push(peg$FAILED);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.PUSH_EMPTY_ARRAY + ":", // PUSH_EMPTY_ARRAY
      "          stack.push([]);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.PUSH_CURR_POS + ":", // PUSH_CURR_POS
      "          stack.push(peg$currPos);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.POP + ":", // POP
      "          stack.pop();",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.POP_CURR_POS + ":", // POP_CURR_POS
      "          peg$currPos = stack.pop();",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.POP_N + ":", // POP_N n
      "          stack.length -= bc[ip + 1];",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.NIP + ":", // NIP
      "          stack.splice(-2, 1);",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.APPEND + ":", // APPEND
      "          stack[stack.length - 2].push(stack.pop());",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.WRAP + ":", // WRAP n
      "          stack.push(stack.splice(stack.length - bc[ip + 1], bc[ip + 1]));",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.TEXT + ":", // TEXT
      "          stack.push(input.substring(stack.pop(), peg$currPos));",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.IF + ":", // IF t, f
      indent10(generateCondition("stack[stack.length - 1]", 0)),
      "",
      "        case " + op.IF_ERROR + ":", // IF_ERROR t, f
      indent10(generateCondition(
        "stack[stack.length - 1] === peg$FAILED",
        0
      )),
      "",
      "        case " + op.IF_NOT_ERROR + ":", // IF_NOT_ERROR t, f
      indent10(
        generateCondition("stack[stack.length - 1] !== peg$FAILED",
          0
        )),
      "",
      "        case " + op.WHILE_NOT_ERROR + ":", // WHILE_NOT_ERROR b
      indent10(generateLoop("stack[stack.length - 1] !== peg$FAILED")),
      "",
      "        case " + op.MATCH_ANY + ":", // MATCH_ANY a, f, ...
      indent10(generateCondition("input.length > peg$currPos", 0)),
      "",
      "        case " + op.MATCH_STRING + ":", // MATCH_STRING s, a, f, ...
      indent10(generateCondition(
        "input.substr(peg$currPos, peg$consts[bc[ip + 1]].length) === peg$consts[bc[ip + 1]]",
        1
      )),
      "",
      "        case " + op.MATCH_STRING_IC + ":", // MATCH_STRING_IC s, a, f, ...
      indent10(generateCondition(
        "input.substr(peg$currPos, peg$consts[bc[ip + 1]].length).toLowerCase() === peg$consts[bc[ip + 1]]",
        1
      )),
      "",
      "        case " + op.MATCH_REGEXP + ":", // MATCH_REGEXP r, a, f, ...
      indent10(generateCondition(
        "peg$consts[bc[ip + 1]].test(input.charAt(peg$currPos))",
        1
      )),
      "",
      "        case " + op.ACCEPT_N + ":", // ACCEPT_N n
      "          stack.push(input.substr(peg$currPos, bc[ip + 1]));",
      "          peg$currPos += bc[ip + 1];",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.ACCEPT_STRING + ":", // ACCEPT_STRING s
      "          stack.push(peg$consts[bc[ip + 1]]);",
      "          peg$currPos += peg$consts[bc[ip + 1]].length;",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.FAIL + ":", // FAIL e
      "          stack.push(peg$FAILED);",
      "          if (peg$silentFails === 0) {",
      "            peg$fail(peg$consts[bc[ip + 1]]);",
      "          }",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.LOAD_SAVED_POS + ":", // LOAD_SAVED_POS p
      "          peg$savedPos = stack[stack.length - 1 - bc[ip + 1]];",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.UPDATE_SAVED_POS + ":", // UPDATE_SAVED_POS
      "          peg$savedPos = peg$currPos;",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.CALL + ":", // CALL f, n, pc, p1, p2, ..., pN
      indent10(generateCall()),
      "",
      "        case " + op.RULE + ":", // RULE r
      "          stack.push(peg$parseRule(bc[ip + 1]));",
      "          ip += 2;",
      "          break;",
      "",
      "        case " + op.SILENT_FAILS_ON + ":", // SILENT_FAILS_ON
      "          peg$silentFails++;",
      "          ip++;",
      "          break;",
      "",
      "        case " + op.SILENT_FAILS_OFF + ":", // SILENT_FAILS_OFF
      "          peg$silentFails--;",
      "          ip++;",
      "          break;",
      "",
      "        default:",
      "          throw new Error(\"Invalid opcode: \" + bc[ip] + \".\");",
      "      }",
      "    }",
      "",
      "    if (ends.length > 0) {",
      "      end = ends.pop();",
      "      ip = ips.pop();",
      "    } else {",
      "      break;",
      "    }",
      "  }"
    ].join("\n"));

    parts.push(indent2(generateRuleFooter("peg$ruleNames[index]", "stack[0]")));
    parts.push("}");

    return parts.join("\n");
  }

  function generateRuleFunction(rule) {
    let parts = [];
    let stackVars = [];
    let code;

    function c(i) {
      return "peg$c" + i;
    } // |consts[i]| of the abstract machine
    function s(i) {
      return "s" + i;
    } // |stack[i]| of the abstract machine

    let stack = {
      sp: -1,
      maxSp: -1,

      push(exprCode) {
        let code = s(++this.sp) + " = " + exprCode + ";";

        if (this.sp > this.maxSp) {
          this.maxSp = this.sp;
        }

        return code;
      },

      pop(n) {
        if (n === undefined) {
          return s(this.sp--);
        } else {
          let values = Array(n);

          for (let i = 0; i < n; i++) {
            values[i] = s(this.sp - n + 1 + i);
          }

          this.sp -= n;

          return values;
        }
      },

      top() {
        return s(this.sp);
      },

      index(i) {
        return s(this.sp - i);
      }
    };

    function compile(bc) {
      let ip = 0;
      let end = bc.length;
      let parts = [];
      let value;

      function compileCondition(cond, argCount) {
        let baseLength = argCount + 3;
        let thenLength = bc[ip + baseLength - 2];
        let elseLength = bc[ip + baseLength - 1];
        let baseSp = stack.sp;
        let thenCode, elseCode, thenSp, elseSp;

        ip += baseLength;
        thenCode = compile(bc.slice(ip, ip + thenLength));
        thenSp = stack.sp;
        ip += thenLength;

        if (elseLength > 0) {
          stack.sp = baseSp;
          elseCode = compile(bc.slice(ip, ip + elseLength));
          elseSp = stack.sp;
          ip += elseLength;

          if (thenSp !== elseSp) {
            throw new Error(
              "Branches of a condition must move the stack pointer in the same way."
            );
          }
        }

        parts.push("if (" + cond + ") {");
        parts.push(indent2(thenCode));
        if (elseLength > 0) {
          parts.push("} else {");
          parts.push(indent2(elseCode));
        }
        parts.push("}");
      }

      function compileLoop(cond) {
        let baseLength = 2;
        let bodyLength = bc[ip + baseLength - 1];
        let baseSp = stack.sp;
        let bodyCode, bodySp;

        ip += baseLength;
        bodyCode = compile(bc.slice(ip, ip + bodyLength));
        bodySp = stack.sp;
        ip += bodyLength;

        if (bodySp !== baseSp) {
          throw new Error("Body of a loop can't move the stack pointer.");
        }

        parts.push("while (" + cond + ") {");
        parts.push(indent2(bodyCode));
        parts.push("}");
      }

      function compileCall() {
        let baseLength = 4;
        let paramsLength = bc[ip + baseLength - 1];

        let value = c(bc[ip + 1]) + "(" +
          bc.slice(ip + baseLength, ip + baseLength + paramsLength).map(
            p => stack.index(p)
          ).join(", ") +
          ")";
        stack.pop(bc[ip + 2]);
        parts.push(stack.push(value));
        ip += baseLength + paramsLength;
      }

      while (ip < end) {
        switch (bc[ip]) {
          case op.PUSH: // PUSH c
            parts.push(stack.push(c(bc[ip + 1])));
            ip += 2;
            break;

          case op.PUSH_CURR_POS: // PUSH_CURR_POS
            parts.push(stack.push("peg$currPos"));
            ip++;
            break;

          case op.PUSH_UNDEFINED: // PUSH_UNDEFINED
            parts.push(stack.push("undefined"));
            ip++;
            break;

          case op.PUSH_NULL: // PUSH_NULL
            parts.push(stack.push("null"));
            ip++;
            break;

          case op.PUSH_FAILED: // PUSH_FAILED
            parts.push(stack.push("peg$FAILED"));
            ip++;
            break;

          case op.PUSH_EMPTY_ARRAY: // PUSH_EMPTY_ARRAY
            parts.push(stack.push("[]"));
            ip++;
            break;

          case op.POP: // POP
            stack.pop();
            ip++;
            break;

          case op.POP_CURR_POS: // POP_CURR_POS
            parts.push("peg$currPos = " + stack.pop() + ";");
            ip++;
            break;

          case op.POP_N: // POP_N n
            stack.pop(bc[ip + 1]);
            ip += 2;
            break;

          case op.NIP: // NIP
            value = stack.pop();
            stack.pop();
            parts.push(stack.push(value));
            ip++;
            break;

          case op.APPEND: // APPEND
            value = stack.pop();
            parts.push(stack.top() + ".push(" + value + ");");
            ip++;
            break;

          case op.WRAP: // WRAP n
            parts.push(
              stack.push("[" + stack.pop(bc[ip + 1]).join(", ") + "]")
            );
            ip += 2;
            break;

          case op.TEXT: // TEXT
            parts.push(
              stack.push("input.substring(" + stack.pop() + ", peg$currPos)")
            );
            ip++;
            break;

          case op.IF: // IF t, f
            compileCondition(stack.top(), 0);
            break;

          case op.IF_ERROR: // IF_ERROR t, f
            compileCondition(stack.top() + " === peg$FAILED", 0);
            break;

          case op.IF_NOT_ERROR: // IF_NOT_ERROR t, f
            compileCondition(stack.top() + " !== peg$FAILED", 0);
            break;

          case op.WHILE_NOT_ERROR: // WHILE_NOT_ERROR b
            compileLoop(stack.top() + " !== peg$FAILED", 0);
            break;

          case op.MATCH_ANY: // MATCH_ANY a, f, ...
            compileCondition("input.length > peg$currPos", 0);
            break;

          case op.MATCH_STRING: // MATCH_STRING s, a, f, ...
            compileCondition(
              eval(ast.consts[bc[ip + 1]]).length > 1 ?
              "input.substr(peg$currPos, " +
              eval(ast.consts[bc[ip + 1]]).length +
              ") === " +
              c(bc[ip + 1]) :
              "input.charCodeAt(peg$currPos) === " +
              eval(ast.consts[bc[ip + 1]]).charCodeAt(0),
              1
            );
            break;

          case op.MATCH_STRING_IC: // MATCH_STRING_IC s, a, f, ...
            compileCondition(
              "input.substr(peg$currPos, " +
              eval(ast.consts[bc[ip + 1]]).length +
              ").toLowerCase() === " +
              c(bc[ip + 1]),
              1
            );
            break;

          case op.MATCH_REGEXP: // MATCH_REGEXP r, a, f, ...
            compileCondition(
              c(bc[ip + 1]) + ".test(input.charAt(peg$currPos))",
              1
            );
            break;

          case op.ACCEPT_N: // ACCEPT_N n
            parts.push(stack.push(
              bc[ip + 1] > 1 ?
              "input.substr(peg$currPos, " + bc[ip + 1] + ")" :
              "input.charAt(peg$currPos)"
            ));
            parts.push(
              bc[ip + 1] > 1 ?
              "peg$currPos += " + bc[ip + 1] + ";" :
              "peg$currPos++;"
            );
            ip += 2;
            break;

          case op.ACCEPT_STRING: // ACCEPT_STRING s
            parts.push(stack.push(c(bc[ip + 1])));
            parts.push(
              eval(ast.consts[bc[ip + 1]]).length > 1 ?
              "peg$currPos += " + eval(ast.consts[bc[ip + 1]]).length + ";" :
              "peg$currPos++;"
            );
            ip += 2;
            break;

          case op.FAIL: // FAIL e
            parts.push(stack.push("peg$FAILED"));
            parts.push("if (peg$silentFails === 0) { peg$fail(" + c(bc[ip + 1]) + "); }");
            ip += 2;
            break;

          case op.LOAD_SAVED_POS: // LOAD_SAVED_POS p
            parts.push("peg$savedPos = " + stack.index(bc[ip + 1]) + ";");
            ip += 2;
            break;

          case op.UPDATE_SAVED_POS: // UPDATE_SAVED_POS
            parts.push("peg$savedPos = peg$currPos;");
            ip++;
            break;

          case op.CALL: // CALL f, n, pc, p1, p2, ..., pN
            compileCall();
            break;

          case op.RULE: // RULE r
            parts.push(stack.push("peg$parse" + ast.rules[bc[ip + 1]].name + "()"));
            ip += 2;
            break;

          case op.SILENT_FAILS_ON: // SILENT_FAILS_ON
            parts.push("peg$silentFails++;");
            ip++;
            break;

          case op.SILENT_FAILS_OFF: // SILENT_FAILS_OFF
            parts.push("peg$silentFails--;");
            ip++;
            break;

          default:
            throw new Error("Invalid opcode: " + bc[ip] + ".");
        }
      }

      return parts.join("\n");
    }

    code = compile(rule.bytecode);

    const outputType = (options && options.returnTypes && options.returnTypes[rule.name]) ?
                       options.returnTypes[rule.name] : "any";
    
    parts.push("function peg$parse" + rule.name + "(): " + outputType +" {");

    if (options.trace) {
      parts.push("  const startPos = peg$currPos;");
    }

    for (let i = 0; i <= stack.maxSp; i++) {
      stackVars[i] = s(i);
    }

    parts.push("  let " + stackVars.join(", ") + ";");

    parts.push(indent2(generateRuleHeader(
      "\"" + js.stringEscape(rule.name) + "\"",
      asts.indexOfRule(ast, rule.name)
    )));
    parts.push(indent2(code));
    parts.push(indent2(generateRuleFooter(
      "\"" + js.stringEscape(rule.name) + "\"",
      s(0)
    )));

    parts.push("}");

    return parts.join("\n");
  }

  function generateToplevel() {
    let parts = [];

    if (options.tspegjs.customHeader) {
      parts.push(options.tspegjs.customHeader);
    }
    parts.push([
      "export interface IFilePosition {",
      "  offset: number;",
      "  line: number;",
      "  column: number;",
      "}",
      "",
      "export interface IFileRange {",
      "  start: IFilePosition;",
      "  end: IFilePosition;",
      "}",
      "",
      "export interface ILiteralExpectation {",
      "  type: \"literal\";",
      "  text: string;",
      "  ignoreCase: boolean;",
      "}",
      "",
      "export interface IClassParts extends Array<string | IClassParts> {}",
      "",
      "export interface IClassExpectation {",
      "  type: \"class\";",
      "  parts: IClassParts;",
      "  inverted: boolean;",
      "  ignoreCase: boolean;",
      "}",
      "",
      "export interface IAnyExpectation {",
      "  type: \"any\";",
      "}",
      "",
      "export interface IEndExpectation {",
      "  type: \"end\";",
      "}",
      "",
      "export interface IOtherExpectation {",
      "  type: \"other\";",
      "  description: string;",
      "}",
      "",
      "export type Expectation = ILiteralExpectation | IClassExpectation | IAnyExpectation | IEndExpectation | IOtherExpectation;",
      "",
      "export class SyntaxError extends Error {",
      "  public static buildMessage(expected: Expectation[], found: string | null) {",
      "    function hex(ch: string): string {",
      "      return ch.charCodeAt(0).toString(16).toUpperCase();",
      "    }",
      "",
      "    function literalEscape(s: string): string {",
      "      return s",
      "        .replace(/\\\\/g, \"\\\\\\\\\")", // backslash
      "        .replace(/\"/g,  \"\\\\\\\"\")", // closing double quote
      "        .replace(/\\0/g, \"\\\\0\")", // null
      "        .replace(/\\t/g, \"\\\\t\")", // horizontal tab
      "        .replace(/\\n/g, \"\\\\n\")", // line feed
      "        .replace(/\\r/g, \"\\\\r\")", // carriage return
      "        .replace(/[\\x00-\\x0F]/g,            (ch) => \"\\\\x0\" + hex(ch) )",
      "        .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, (ch) => \"\\\\x\"  + hex(ch) );",
      "    }",
      "",
      "    function classEscape(s: string): string {",
      "      return s",
      "        .replace(/\\\\/g, \"\\\\\\\\\")", // backslash
      "        .replace(/\\]/g, \"\\\\]\")", // closing bracket
      "        .replace(/\\^/g, \"\\\\^\")", // caret
      "        .replace(/-/g,  \"\\\\-\")", // dash
      "        .replace(/\\0/g, \"\\\\0\")", // null
      "        .replace(/\\t/g, \"\\\\t\")", // horizontal tab
      "        .replace(/\\n/g, \"\\\\n\")", // line feed
      "        .replace(/\\r/g, \"\\\\r\")", // carriage return
      "        .replace(/[\\x00-\\x0F]/g,            (ch) => \"\\\\x0\" + hex(ch) )",
      "        .replace(/[\\x10-\\x1F\\x7F-\\x9F]/g, (ch) => \"\\\\x\"  + hex(ch) );",
      "    }",
      "",
      "    function describeExpectation(expectation: Expectation) {",
      "      switch (expectation.type) {",
      "        case \"literal\":",
      "          return \"\\\"\" + literalEscape(expectation.text) + \"\\\"\";",
      "        case \"class\":",
      "          const escapedParts = expectation.parts.map((part) => {",
      "            return Array.isArray(part)",
      "              ? classEscape(part[0] as string) + \"-\" + classEscape(part[1] as string)",
      "              : classEscape(part);",
      "          });",
      "",
      "          return \"[\" + (expectation.inverted ? \"^\" : \"\") + escapedParts + \"]\";",
      "        case \"any\":",
      "          return \"any character\";",
      "        case \"end\":",
      "          return \"end of input\";",
      "        case \"other\":",
      "          return expectation.description;",
      "      }",
      "    }",
      "",
      "    function describeExpected(expected1: Expectation[]) {",
      "      const descriptions = expected1.map(describeExpectation);",
      "      let i;",
      "      let j;",
      "",
      "      descriptions.sort();",
      "",
      "      if (descriptions.length > 0) {",
      "        for (i = 1, j = 1; i < descriptions.length; i++) {",
      "          if (descriptions[i - 1] !== descriptions[i]) {",
      "            descriptions[j] = descriptions[i];",
      "            j++;",
      "          }",
      "        }",
      "        descriptions.length = j;",
      "      }",
      "",
      "      switch (descriptions.length) {",
      "        case 1:",
      "          return descriptions[0];",
      "",
      "        case 2:",
      "          return descriptions[0] + \" or \" + descriptions[1];",
      "",
      "        default:",
      "          return descriptions.slice(0, -1).join(\", \")",
      "            + \", or \"",
      "            + descriptions[descriptions.length - 1];",
      "      }",
      "    }",
      "",
      "    function describeFound(found1: string | null) {",
      "      return found1 ? \"\\\"\" + literalEscape(found1) + \"\\\"\" : \"end of input\";",
      "    }",
      "",
      "    return \"Expected \" + describeExpected(expected) + \" but \" + describeFound(found) + \" found.\";",
      "  }",
      "",
      "  public message: string;",
      "  public expected: Expectation[];",
      "  public found: string | null;",
      "  public location: IFileRange;",
      "  public name: string;",
      "",
      "  constructor(message: string, expected: Expectation[], found: string | null, location: IFileRange) {",
      "    super();",
      "    this.message = message;",
      "    this.expected = expected;",
      "    this.found = found;",
      "    this.location = location;",
      "    this.name = \"SyntaxError\";",
      "",
      "    if (typeof (Error as any).captureStackTrace === \"function\") {",
      "      (Error as any).captureStackTrace(this, SyntaxError);",
      "    }",
      "  }",
      "}",
      ""
    ].join("\n"));

    if (options.trace) {
      parts.push([
        "export interface ITraceEvent {",
        "  type: string;",
        "  rule: string;",
        "  result?: any;",
        "  location: IFileRange;",
        "}",
        "",
        "export class DefaultTracer {",
        "  private indentLevel: number;",
        "",
        "  constructor() {",
        "    this.indentLevel = 0;",
        "  }",
        "",
        "  public trace(event: ITraceEvent) {",
        "    const that = this;",
        "",
        "    function log(evt: ITraceEvent) {",
        "      function repeat(text: string, n: number) {",
        "         let result = \"\", i;",
        "",
        "         for (i = 0; i < n; i++) {",
        "           result += text;",
        "         }",
        "",
        "         return result;",
        "      }",
        "",
        "      function pad(text: string, length: number) {",
        "        return text + repeat(\" \", length - text.length);",
        "      }",
        "",
        "      if (typeof console === \"object\") {", // IE 8-10
        "        console.log(",
        "          evt.location.start.line + \":\" + evt.location.start.column + \"-\"",
        "            + evt.location.end.line + \":\" + evt.location.end.column + \" \"",
        "            + pad(evt.type, 10) + \" \"",
        "            + repeat(\"  \", that.indentLevel) + evt.rule",
        "        );",
        "      }",
        "    }",
        "",
        "    switch (event.type) {",
        "      case \"rule.enter\":",
        "        log(event);",
        "        this.indentLevel++;",
        "        break;",
        "",
        "      case \"rule.match\":",
        "        this.indentLevel--;",
        "        log(event);",
        "        break;",
        "",
        "      case \"rule.fail\":",
        "        this.indentLevel--;",
        "        log(event);",
        "        break;",
        "",
        "      default:",
        "        throw new Error(\"Invalid event type: \" + event.type + \".\");",
        "    }",
        "  }",
        "}",
        ""
      ].join("\n"));
    }

    if (options.cache) {
      parts.push([
        "export interface ICached {",
        "  nextPos: number;",
        "  result: any;",
        "}",
        "",
      ].join("\n"));
    }

    parts.push([
      "function peg$parse(input: string, options?: IParseOptions) {",
      "  options = options !== undefined ? options : {};",
      "",
      "  const peg$FAILED = {};",
      ""
    ].join("\n"));

    if (options.optimize === "size") {
      let startRuleIndices = "{ " +
        options.allowedStartRules.map(
          r => r + ": " + asts.indexOfRule(ast, r)
        ).join(", ") +
        " }";
      let startRuleIndex = asts.indexOfRule(ast, options.allowedStartRules[0]);

      parts.push([
        "  const peg$startRuleIndices = " + startRuleIndices + ";",
        "  const peg$startRuleIndex = " + startRuleIndex + ";"
      ].join("\n"));
    } else {
      let startRuleFunctions = "{ " +
        options.allowedStartRules.map(
          r => r + ": peg$parse" + r
        ).join(", ") +
        " }";
      let startRuleFunction = "peg$parse" + options.allowedStartRules[0];

      parts.push([
        "  const peg$startRuleFunctions: {[id: string]: any} = " + startRuleFunctions + ";",
        "  let peg$startRuleFunction: () => any = " + startRuleFunction + ";"
      ].join("\n"));
    }

    parts.push("");

    parts.push(indent2(generateTables()));

    parts.push([
      "",
      "  let peg$currPos = 0;",
      "  let peg$savedPos = 0;",
      "  const peg$posDetailsCache = [{ line: 1, column: 1 }];",
      "  let peg$maxFailPos = 0;",
      "  let peg$maxFailExpected: any[] = [];",
      "  let peg$silentFails = 0;", // 0 = report failures, > 0 = silence failures
      ""
    ].join("\n"));

    if (options.cache) {
      parts.push([
        "  const peg$resultsCache: {[id: number]: ICached} = {};",
        ""
      ].join("\n"));
    }

    if (options.trace) {
      if (options.optimize === "size") {
        let ruleNames = "[" +
          ast.rules.map(
            r => "\"" + js.stringEscape(r.name) + "\""
          ).join(", ") +
          "]";

        parts.push([
          "  let peg$ruleNames = " + ruleNames + ";",
          ""
        ].join("\n"));
      }

      parts.push([
        "  const peg$tracer = \"tracer\" in options ? options.tracer : new DefaultTracer();",
        ""
      ].join("\n"));
    }

    parts.push([
      "  let peg$result;",
      ""
    ].join("\n"));

    if (options.optimize === "size") {
      parts.push([
        "  if (options.startRule !== undefined) {",
        "    if (!(options.startRule in peg$startRuleIndices)) {",
        "      throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");",
        "    }",
        "",
        "    peg$startRuleIndex = peg$startRuleIndices[options.startRule];",
        "  }"
      ].join("\n"));
    } else {
      parts.push([
        "  if (options.startRule !== undefined) {",
        "    if (!(options.startRule in peg$startRuleFunctions)) {",
        "      throw new Error(\"Can't start parsing from rule \\\"\" + options.startRule + \"\\\".\");",
        "    }",
        "",
        "    peg$startRuleFunction = peg$startRuleFunctions[options.startRule];",
        "  }"
      ].join("\n"));
    }

    parts.push([
      "",
      "  function text(): string {",
      "    return input.substring(peg$savedPos, peg$currPos);",
      "  }",
      "",
      "  function location(): IFileRange {",
      "    return peg$computeLocation(peg$savedPos, peg$currPos);",
      "  }",
      "",
      "  function expected(description: string, location1?: IFileRange) {",
      "    location1 = location1 !== undefined",
      "      ? location1",
      "      : peg$computeLocation(peg$savedPos, peg$currPos);",
      "",
      "    throw peg$buildStructuredError(",
      "      [peg$otherExpectation(description)],",
      "      input.substring(peg$savedPos, peg$currPos),",
      "      location1",
      "    );",
      "  }",
      "",
      "  function error(message: string, location1?: IFileRange) {",
      "    location1 = location1 !== undefined",
      "      ? location1",
      "      : peg$computeLocation(peg$savedPos, peg$currPos);",
      "",
      "    throw peg$buildSimpleError(message, location1);",
      "  }",
      "",
      "  function peg$literalExpectation(text1: string, ignoreCase: boolean): ILiteralExpectation {",
      "    return { type: \"literal\", text: text1, ignoreCase: ignoreCase };",
      "  }",
      "",
      "  function peg$classExpectation(parts: IClassParts, inverted: boolean, ignoreCase: boolean): IClassExpectation {",
      "    return { type: \"class\", parts: parts, inverted: inverted, ignoreCase: ignoreCase };",
      "  }",
      "",
      "  function peg$anyExpectation(): IAnyExpectation {",
      "    return { type: \"any\" };",
      "  }",
      "",
      "  function peg$endExpectation(): IEndExpectation {",
      "    return { type: \"end\" };",
      "  }",
      "",
      "  function peg$otherExpectation(description: string): IOtherExpectation {",
      "    return { type: \"other\", description: description };",
      "  }",
      "",
      "  function peg$computePosDetails(pos: number) {",
      "    let details = peg$posDetailsCache[pos];",
      "    let p;",
      "",
      "    if (details) {",
      "      return details;",
      "    } else {",
      "      p = pos - 1;",
      "      while (!peg$posDetailsCache[p]) {",
      "        p--;",
      "      }",
      "",
      "      details = peg$posDetailsCache[p];",
      "      details = {",
      "        line: details.line,",
      "        column: details.column",
      "      };",
      "",
      "      while (p < pos) {",
      "        if (input.charCodeAt(p) === 10) {",
      "          details.line++;",
      "          details.column = 1;",
      "        } else {",
      "          details.column++;",
      "        }",
      "",
      "        p++;",
      "      }",
      "",
      "      peg$posDetailsCache[pos] = details;",
      "",
      "      return details;",
      "    }",
      "  }",
      "",
      "  function peg$computeLocation(startPos: number, endPos: number): IFileRange {",
      "    const startPosDetails = peg$computePosDetails(startPos);",
      "    const endPosDetails = peg$computePosDetails(endPos);",
      "",
      "    return {",
      "      start: {",
      "        offset: startPos,",
      "        line: startPosDetails.line,",
      "        column: startPosDetails.column",
      "      },",
      "      end: {",
      "        offset: endPos,",
      "        line: endPosDetails.line,",
      "        column: endPosDetails.column",
      "      }",
      "    };",
      "  }",
      "",
      "  function peg$fail(expected1: Expectation) {",
      "    if (peg$currPos < peg$maxFailPos) { return; }",
      "",
      "    if (peg$currPos > peg$maxFailPos) {",
      "      peg$maxFailPos = peg$currPos;",
      "      peg$maxFailExpected = [];",
      "    }",
      "",
      "    peg$maxFailExpected.push(expected1);",
      "  }",
      "",
      "  function peg$buildSimpleError(message: string, location1: IFileRange) {",
      "    return new SyntaxError(message, [], \"\", location1);",
      "  }",
      "",
      "  function peg$buildStructuredError(expected1: Expectation[], found: string | null, location1: IFileRange) {",
      "    return new SyntaxError(",
      "      SyntaxError.buildMessage(expected1, found),",
      "      expected1,",
      "      found,",
      "      location1",
      "    );",
      "  }",
      ""
    ].join("\n"));

    if (options.optimize === "size") {
      parts.push(indent2(generateInterpreter()));
      parts.push("");
    } else {
      ast.rules.forEach(rule => {
        parts.push(indent2(generateRuleFunction(rule)));
        parts.push("");
      });
    }

    if (ast.initializer) {
      parts.push(indent2(ast.initializer.code));
      parts.push("");
    }

    if (options.optimize === "size") {
      parts.push("  peg$result = peg$parseRule(peg$startRuleIndex);");
    } else {
      parts.push("  peg$result = peg$startRuleFunction();");
    }

    parts.push([
      "",
      "  if (peg$result !== peg$FAILED && peg$currPos === input.length) {",
      "    return peg$result;",
      "  } else {",
      "    if (peg$result !== peg$FAILED && peg$currPos < input.length) {",
      "      peg$fail(peg$endExpectation());",
      "    }",
      "",
      "    throw peg$buildStructuredError(",
      "      peg$maxFailExpected,",
      "      peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,",
      "      peg$maxFailPos < input.length",
      "        ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)",
      "        : peg$computeLocation(peg$maxFailPos, peg$maxFailPos)",
      "    );",
      "  }",
      "}"
    ].join("\n"));

    return parts.join("\n");
  }

  function generateWrapper(toplevelCode) {
    function generateGeneratedByComment() {
      let res = [];
      if (!options.tspegjs.noTslint) {
        if (options.tspegjs.tslintIgnores) {
          // apply user custom exclusions
          res = res.concat(
            options.tspegjs.tslintIgnores
                .split(",")
                .map((rule) => "// tslint:disable:" + rule)
          );
        } else {
          // apply default tslint excusions
          res = res.concat([
            "// tslint:disable:only-arrow-functions",
            "// tslint:disable:object-literal-shorthand",
            "// tslint:disable:trailing-comma",
            "// tslint:disable:object-literal-sort-keys",
            "// tslint:disable:one-variable-per-declaration",
            "// tslint:disable:max-line-length",
            "// tslint:disable:no-consecutive-blank-lines",
            "// tslint:disable:align",
            options.trace ? "// tslint:disable:no-console" : ""
          ]); 
        }
      }
      res = res.concat([
        "",
        "// Generated by PEG.js v. " + pegJsVersion + " (ts-pegjs plugin v. " + pluginVersion + " )",
        "//",
        "// https://pegjs.org/   https://github.com/metadevpro/ts-pegjs"
      ]);

      return res.join("\n");
    }

    function generateParserObject() {
      const optionsType = `export interface IParseOptions {
  filename?: string;
  startRule?: string;
  tracer?: any;
  [key: string]: any;
}`;
      const parseFunctionType = "export type ParseFunction = (input: string, options?: IParseOptions) => any;";
      const parseExport = "export const parse: ParseFunction = peg$parse;";

      return options.trace ?
        [
          optionsType,
          parseFunctionType,
          parseExport,
          ""
          // "{",
          // "  SyntaxError: peg$SyntaxError,",
          // "  DefaultTracer: peg$DefaultTracer,",
          // "  parse: peg$parse",
          // "}"
        ].join("\n") :
        [
          optionsType,
          parseFunctionType,
          parseExport,
          ""
          // "{",
          // "  SyntaxError: peg$SyntaxError,",
          // "  parse: peg$parse",
          // "}"
        ].join("\n");
    }

    function generateParserExports() {
      return options.trace ?
        [
          "{",
          "  SyntaxError as SyntaxError,",
          "  DefaultTracer as DefaultTracer,",
          "  peg$parse as parse",
          "}"
        ].join("\n") :
        [
          "{",
          "  SyntaxError as SyntaxError,",
          "  peg$parse as parse",
          "}"
        ].join("\n");
    }

    let generators = {
      bare() {
        return [
          generateGeneratedByComment(),
          // "(function() {",
          // "  \"use strict\";",
          "",
          toplevelCode,
          "",
          //indent2("return " + generateParserObject() + ";"),
          generateParserObject(),
          //"})()"
        ].join("\n");
      },

      commonjs() {
        let parts = [];
        let dependencyVars = Object.keys(options.dependencies);

        parts.push([
          generateGeneratedByComment(),
          "",
          "\"use strict\";",
          ""
        ].join("\n"));

        if (dependencyVars.length > 0) {
          dependencyVars.forEach(variable => {
            parts.push("let " + variable +
              " = require(\"" +
              js.stringEscape(options.dependencies[variable]) +
              "\");"
            );
          });
          parts.push("");
        }

        parts.push([
          toplevelCode,
          "",
          //"module.exports = " + generateParserObject() + ";",
          generateParserObject(),
          ""
        ].join("\n"));

        return parts.join("\n");
      },

      es() {
        let parts = [];
        let dependencyVars = Object.keys(options.dependencies);

        parts.push(
          generateGeneratedByComment(),
          ""
        );

        if (dependencyVars.length > 0) {
          dependencyVars.forEach(variable => {
            parts.push("import " + variable +
              " from \"" +
              js.stringEscape(options.dependencies[variable]) +
              "\";"
            );
          });
          parts.push("");
        }

        parts.push(
          toplevelCode,
          "",
          "export " + generateParserExports() + ";",
          ""
        );

        return parts.join("\n");
      },

      amd() {
        let dependencyVars = Object.keys(options.dependencies);
        let dependencyIds = dependencyVars.map(v => options.dependencies[v]);
        let dependencies = "[" +
          dependencyIds.map(
            id => "\"" + js.stringEscape(id) + "\""
          ).join(", ") +
          "]";
        let params = dependencyVars.map(v => v + ": any").join(", ");

        return [
          generateGeneratedByComment(),
          "define(" + dependencies + ", function(" + params + ") {",
          "  \"use strict\";",
          "",
          indent2(toplevelCode),
          "",
          indent2("return " + generateParserObject() + ";"),
          "});",
          ""
        ].join("\n");
      },

      globals() {
        return [
          generateGeneratedByComment(),
          "(function(root) {",
          "  \"use strict\";",
          "",
          indent2(toplevelCode),
          "",
          indent2("root." + options.exportVar + " = " + generateParserObject() + ";"),
          "})(this);",
          ""
        ].join("\n");
      },

      umd() {
        let parts = [];
        let dependencyVars = Object.keys(options.dependencies);
        let dependencyIds = dependencyVars.map(v => options.dependencies[v]);
        let dependencies = "[" +
          dependencyIds.map(
            id => "\"" + js.stringEscape(id) + "\""
          ).join(", ") +
          "]";
        let requires = dependencyIds.map(
          id => "require(\"" + js.stringEscape(id) + "\")"
        ).join(", ");
        let params = dependencyVars.map(v => v + ": any").join(", ");

        parts.push([
          generateGeneratedByComment(),
          "(function(root, factory) {",
          "  if (typeof define === \"function\" && define.amd) {",
          "    define(" + dependencies + ", factory);",
          "  } else if (typeof module === \"object\" && module.exports) {",
          "    module.exports = factory(" + requires + ");"
        ].join("\n"));

        if (options.exportVar !== null) {
          parts.push([
            "  } else {",
            "    root." + options.exportVar + " = factory();"
          ].join("\n"));
        }

        parts.push([
          "  }",
          "})(this, function(" + params + ") {",
          "  \"use strict\";",
          "",
          indent2(toplevelCode),
          "",
          indent2("return " + generateParserObject() + ";"),
          "});",
          ""
        ].join("\n"));

        return parts.join("\n");
      }
    };

    return generators[options.format]();
  }

  ast.code = generateWrapper(generateToplevel());
}
42463
function generateBundle(locale, messages, reactElements, options) {
  var builtContent;
  var onBuildWrite = options.onBuildWrite || defaultOnBuildWrite;
  options = options || {};

  init();

  assertLocale(locale);
  assertMessages(messages);
  assertReactElements(reactElements);

  // Load i18n content.
  loadCldr(locale);
  loadMessages(messages);

  // Set locale.
  Globalize.locale(locale);

  // Have react to render all passed components, therefore the formatters in
  // use will be created in Globalize.cache.
  _reactElements(reactElements).forEach(function(reactElement) {
    React.renderToString(reactElement);
   });

  // Compile all generated formatters.
  builtContent = GlobalizeCompiler(Globalize.cache);

  // Cleanup.
  Globalize.cache = {};

  return onBuildWrite(locale, builtContent);
}
434245
function resolvePrefixedValues(snippetObj, isImportant, syntax) {
		var prefixes = [];
		var lookup = {};

		var parts = cssEditTree.findParts(snippetObj.value);
		parts.reverse();
		parts.forEach(function(p) {
			var partValue = p.substring(snippetObj.value);
			(findVendorPrefixes(partValue) || []).forEach(function(prefix) {
				if (!lookup[prefix]) {
					lookup[prefix] = snippetObj.value;
					prefixes.push(prefix);
				}

				lookup[prefix] = utils.replaceSubstring(lookup[prefix], '-' + prefix + '-' + partValue, p);
			});
		});

		return prefixes.map(function(prefix) {
			return transformSnippet(snippetObj.name + ':' + lookup[prefix], isImportant, syntax);
		});
	}