function Statement(t, x) {
    var i, label, n, n2, p, c, ss, tt = t.get(true), tt2, x2, x3;

    // Cases for statements ending in a right curly return early, avoiding the
    // common semicolon insertion magic after this switch.
    switch (tt) {
      case FUNCTION:
        // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't.
        return FunctionDefinition(t, x, true,
                                  (x.nesting !== NESTING_TOP)
                                  ? STATEMENT_FORM
                                  : DECLARED_FORM);

      case LEFT_CURLY:
        n = new Node(t, blockInit());
        Statements(t, x.update({ parentBlock: n }).pushTarget(n).nest(NESTING_SHALLOW), n);
        t.mustMatch(RIGHT_CURLY);
        return n;

      case IF:
        n = new Node(t);
        n.condition = HeadExpression(t, x);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        n.thenPart = Statement(t, x2);
        n.elsePart = t.match(ELSE) ? Statement(t, x2) : null;
        return n;

      case SWITCH:
        // This allows CASEs after a DEFAULT, which is in the standard.
        n = new Node(t, { cases: [], defaultIndex: -1 });
        n.discriminant = HeadExpression(t, x);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        t.mustMatch(LEFT_CURLY);
        while ((tt = t.get()) !== RIGHT_CURLY) {
            switch (tt) {
              case DEFAULT:
                if (n.defaultIndex >= 0)
                    throw t.newSyntaxError("More than one switch default");
                // FALL THROUGH
              case CASE:
                n2 = new Node(t);
                if (tt === DEFAULT)
                    n.defaultIndex = n.cases.length;
                else
                    n2.caseLabel = Expression(t, x2, COLON);
                break;

              default:
                throw t.newSyntaxError("Invalid switch case");
            }
            t.mustMatch(COLON);
            n2.statements = new Node(t, blockInit());
            while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT &&
                    tt !== RIGHT_CURLY)
                n2.statements.push(Statement(t, x2));
            n.cases.push(n2);
        }
        return n;

      case FOR:
        n = new Node(t, LOOP_INIT);
        if (t.match(IDENTIFIER)) {
            if (t.token.value === "each")
                n.isEach = true;
            else
                t.unget();
        }
        if (!x.parenFreeMode)
            t.mustMatch(LEFT_PAREN);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        x3 = x.update({ inForLoopInit: true });
        if ((tt = t.peek()) !== SEMICOLON) {
            if (tt === VAR || tt === CONST) {
                t.get();
                n2 = Variables(t, x3);
            } else if (tt === LET) {
                t.get();
                if (t.peek() === LEFT_PAREN) {
                    n2 = LetBlock(t, x3, false);
                } else {
                    // Let in for head, we need to add an implicit block
                    // around the rest of the for.
                    x3.parentBlock = n;
                    n.varDecls = [];
                    n2 = Variables(t, x3);
                }
            } else {
                n2 = Expression(t, x3);
            }
        }
        if (n2 && t.match(IN)) {
            n.type = FOR_IN;
            n.object = Expression(t, x3);
            if (n2.type === VAR || n2.type === LET) {
                c = n2.children;

                // Destructuring turns one decl into multiples, so either
                // there must be only one destructuring or only one
                // decl.
                if (c.length !== 1 && n2.destructurings.length !== 1) {
                    throw new SyntaxError("Invalid for..in left-hand side",
                                          t.filename, n2.lineno);
                }
                if (n2.destructurings.length > 0) {
                    n.iterator = n2.destructurings[0];
                } else {
                    n.iterator = c[0];
                }
                n.varDecl = n2;
            } else {
                if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
                    n2.destructuredNames = checkDestructuring(t, x3, n2);
                }
                n.iterator = n2;
            }
        } else {
            n.setup = n2;
            t.mustMatch(SEMICOLON);
            if (n.isEach)
                throw t.newSyntaxError("Invalid for each..in loop");
            n.condition = (t.peek() === SEMICOLON)
                          ? null
                          : Expression(t, x3);
            t.mustMatch(SEMICOLON);
            tt2 = t.peek();
            n.update = (x.parenFreeMode
                        ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2]
                        : tt2 === RIGHT_PAREN)
                       ? null
                       : Expression(t, x3);
        }
        if (!x.parenFreeMode)
            t.mustMatch(RIGHT_PAREN);
        n.body = Statement(t, x2);
        return n;

      case WHILE:
        n = new Node(t, { isLoop: true });
        n.condition = HeadExpression(t, x);
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        return n;

      case DO:
        n = new Node(t, { isLoop: true });
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        t.mustMatch(WHILE);
        n.condition = HeadExpression(t, x);
        if (!x.ecmaStrictMode) {
            // <script language="JavaScript"> (without version hints) may need
            // automatic semicolon insertion without a newline after do-while.
            // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945.
            t.match(SEMICOLON);
            return n;
        }
        break;

      case BREAK:
      case CONTINUE:
        n = new Node(t);

        // handle the |foo: break foo;| corner case
        x2 = x.pushTarget(n);

        if (t.peekOnSameLine() === IDENTIFIER) {
            t.get();
            n.label = t.token.value;
        }

        n.target = n.label
                 ? x2.labeledTargets.find(function(target) { return target.labels.has(n.label) })
                 : x2.defaultTarget;

        if (!n.target)
            throw t.newSyntaxError("Invalid " + ((tt === BREAK) ? "break" : "continue"));
        if (!n.target.isLoop && tt === CONTINUE)
            throw t.newSyntaxError("Invalid continue");

        break;

      case TRY:
        n = new Node(t, { catchClauses: [] });
        n.tryBlock = Block(t, x);
        while (t.match(CATCH)) {
            n2 = new Node(t);
            p = MaybeLeftParen(t, x);
            switch (t.get()) {
              case LEFT_BRACKET:
              case LEFT_CURLY:
                // Destructured catch identifiers.
                t.unget();
                n2.varName = DestructuringExpression(t, x, true);
                break;
              case IDENTIFIER:
                n2.varName = t.token.value;
                break;
              default:
                throw t.newSyntaxError("missing identifier in catch");
                break;
            }
            if (t.match(IF)) {
                if (x.ecma3OnlyMode)
                    throw t.newSyntaxError("Illegal catch guard");
                if (n.catchClauses.length && !n.catchClauses.top().guard)
                    throw t.newSyntaxError("Guarded catch after unguarded");
                n2.guard = Expression(t, x);
            }
            MaybeRightParen(t, p);
            n2.block = Block(t, x);
            n.catchClauses.push(n2);
        }
        if (t.match(FINALLY))
            n.finallyBlock = Block(t, x);
        if (!n.catchClauses.length && !n.finallyBlock)
            throw t.newSyntaxError("Invalid try statement");
        return n;

      case CATCH:
      case FINALLY:
        throw t.newSyntaxError(definitions.tokens[tt] + " without preceding try");

      case THROW:
        n = new Node(t);
        n.exception = Expression(t, x);
        break;

      case RETURN:
        n = ReturnOrYield(t, x);
        break;

      case WITH:
        n = new Node(t);
        n.object = HeadExpression(t, x);
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        return n;

      case VAR:
      case CONST:
        n = Variables(t, x);
        break;

      case LET:
        if (t.peek() === LEFT_PAREN)
            n = LetBlock(t, x, true);
        else
            n = Variables(t, x);
        break;

      case DEBUGGER:
        n = new Node(t);
        break;

      case NEWLINE:
      case SEMICOLON:
        n = new Node(t, { type: SEMICOLON });
        n.expression = null;
        return n;

      default:
        if (tt === IDENTIFIER) {
            tt = t.peek();
            // Labeled statement.
            if (tt === COLON) {
                label = t.token.value;
                if (x.allLabels.has(label))
                    throw t.newSyntaxError("Duplicate label");
                t.get();
                n = new Node(t, { type: LABEL, label: label });
                n.statement = Statement(t, x.pushLabel(label).nest(NESTING_SHALLOW));
                n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement;
                return n;
            }
        }

        // Expression statement.
        // We unget the current token to parse the expression as a whole.
        n = new Node(t, { type: SEMICOLON });
        t.unget();
        n.expression = Expression(t, x);
        n.end = n.expression.end;
        break;
    }

    MagicalSemicolon(t);
    return n;
}
function Statement(t, x) {
    var i, label, n, n2, p, c, ss, tt = t.get(true), tt2, x2, x3;

    
    
    switch (tt) {
      case FUNCTION:
        
        return FunctionDefinition(t, x, true,
                                  (x.nesting !== NESTING_TOP)
                                  ? STATEMENT_FORM
                                  : DECLARED_FORM);

      case LEFT_CURLY:
        n = new Node(t, blockInit());
        Statements(t, x.update({ parentBlock: n }).pushTarget(n).nest(NESTING_SHALLOW), n);
        t.mustMatch(RIGHT_CURLY);
        return n;

      case IF:
        n = new Node(t);
        n.condition = HeadExpression(t, x);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        n.thenPart = Statement(t, x2);
        n.elsePart = t.match(ELSE) ? Statement(t, x2) : null;
        return n;

      case SWITCH:
        
        n = new Node(t, { cases: [], defaultIndex: -1 });
        n.discriminant = HeadExpression(t, x);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        t.mustMatch(LEFT_CURLY);
        while ((tt = t.get()) !== RIGHT_CURLY) {
            switch (tt) {
              case DEFAULT:
                if (n.defaultIndex >= 0)
                    throw t.newSyntaxError("More than one switch default");
                
              case CASE:
                n2 = new Node(t);
                if (tt === DEFAULT)
                    n.defaultIndex = n.cases.length;
                else
                    n2.caseLabel = Expression(t, x2, COLON);
                break;

              default:
                throw t.newSyntaxError("Invalid switch case");
            }
            t.mustMatch(COLON);
            n2.statements = new Node(t, blockInit());
            while ((tt=t.peek(true)) !== CASE && tt !== DEFAULT &&
                    tt !== RIGHT_CURLY)
                n2.statements.push(Statement(t, x2));
            n.cases.push(n2);
        }
        return n;

      case FOR:
        n = new Node(t, LOOP_INIT);
        if (t.match(IDENTIFIER)) {
            if (t.token.value === "each")
                n.isEach = true;
            else
                t.unget();
        }
        if (!x.parenFreeMode)
            t.mustMatch(LEFT_PAREN);
        x2 = x.pushTarget(n).nest(NESTING_DEEP);
        x3 = x.update({ inForLoopInit: true });
        if ((tt = t.peek()) !== SEMICOLON) {
            if (tt === VAR || tt === CONST) {
                t.get();
                n2 = Variables(t, x3);
            } else if (tt === LET) {
                t.get();
                if (t.peek() === LEFT_PAREN) {
                    n2 = LetBlock(t, x3, false);
                } else {
                    
                    
                    x3.parentBlock = n;
                    n.varDecls = [];
                    n2 = Variables(t, x3);
                }
            } else {
                n2 = Expression(t, x3);
            }
        }
        if (n2 && t.match(IN)) {
            n.type = FOR_IN;
            n.object = Expression(t, x3);
            if (n2.type === VAR || n2.type === LET) {
                c = n2.children;

                
                
                
                if (c.length !== 1 && n2.destructurings.length !== 1) {
                    throw new SyntaxError("Invalid for..in left-hand side",
                                          t.filename, n2.lineno);
                }
                if (n2.destructurings.length > 0) {
                    n.iterator = n2.destructurings[0];
                } else {
                    n.iterator = c[0];
                }
                n.varDecl = n2;
            } else {
                if (n2.type === ARRAY_INIT || n2.type === OBJECT_INIT) {
                    n2.destructuredNames = checkDestructuring(t, x3, n2);
                }
                n.iterator = n2;
            }
        } else {
            n.setup = n2;
            t.mustMatch(SEMICOLON);
            if (n.isEach)
                throw t.newSyntaxError("Invalid for each..in loop");
            n.condition = (t.peek() === SEMICOLON)
                          ? null
                          : Expression(t, x3);
            t.mustMatch(SEMICOLON);
            tt2 = t.peek();
            n.update = (x.parenFreeMode
                        ? tt2 === LEFT_CURLY || definitions.isStatementStartCode[tt2]
                        : tt2 === RIGHT_PAREN)
                       ? null
                       : Expression(t, x3);
        }
        if (!x.parenFreeMode)
            t.mustMatch(RIGHT_PAREN);
        n.body = Statement(t, x2);
        return n;

      case WHILE:
        n = new Node(t, { isLoop: true });
        n.condition = HeadExpression(t, x);
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        return n;

      case DO:
        n = new Node(t, { isLoop: true });
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        t.mustMatch(WHILE);
        n.condition = HeadExpression(t, x);
        if (!x.ecmaStrictMode) {
            
            
            
            t.match(SEMICOLON);
            return n;
        }
        break;

      case BREAK:
      case CONTINUE:
        n = new Node(t);

        
        x2 = x.pushTarget(n);

        if (t.peekOnSameLine() === IDENTIFIER) {
            t.get();
            n.label = t.token.value;
        }

        n.target = n.label
                 ? x2.labeledTargets.find(function(target) { return target.labels.has(n.label) })
                 : x2.defaultTarget;

        if (!n.target)
            throw t.newSyntaxError("Invalid " + ((tt === BREAK) ? "break" : "continue"));
        if (!n.target.isLoop && tt === CONTINUE)
            throw t.newSyntaxError("Invalid continue");

        break;

      case TRY:
        n = new Node(t, { catchClauses: [] });
        n.tryBlock = Block(t, x);
        while (t.match(CATCH)) {
            n2 = new Node(t);
            p = MaybeLeftParen(t, x);
            switch (t.get()) {
              case LEFT_BRACKET:
              case LEFT_CURLY:
                
                t.unget();
                n2.varName = DestructuringExpression(t, x, true);
                break;
              case IDENTIFIER:
                n2.varName = t.token.value;
                break;
              default:
                throw t.newSyntaxError("missing identifier in catch");
                break;
            }
            if (t.match(IF)) {
                if (x.ecma3OnlyMode)
                    throw t.newSyntaxError("Illegal catch guard");
                if (n.catchClauses.length && !n.catchClauses.top().guard)
                    throw t.newSyntaxError("Guarded catch after unguarded");
                n2.guard = Expression(t, x);
            }
            MaybeRightParen(t, p);
            n2.block = Block(t, x);
            n.catchClauses.push(n2);
        }
        if (t.match(FINALLY))
            n.finallyBlock = Block(t, x);
        if (!n.catchClauses.length && !n.finallyBlock)
            throw t.newSyntaxError("Invalid try statement");
        return n;

      case CATCH:
      case FINALLY:
        throw t.newSyntaxError(definitions.tokens[tt] + " without preceding try");

      case THROW:
        n = new Node(t);
        n.exception = Expression(t, x);
        break;

      case RETURN:
        n = ReturnOrYield(t, x);
        break;

      case WITH:
        n = new Node(t);
        n.object = HeadExpression(t, x);
        n.body = Statement(t, x.pushTarget(n).nest(NESTING_DEEP));
        return n;

      case VAR:
      case CONST:
        n = Variables(t, x);
        break;

      case LET:
        if (t.peek() === LEFT_PAREN)
            n = LetBlock(t, x, true);
        else
            n = Variables(t, x);
        break;

      case DEBUGGER:
        n = new Node(t);
        break;

      case NEWLINE:
      case SEMICOLON:
        n = new Node(t, { type: SEMICOLON });
        n.expression = null;
        return n;

      default:
        if (tt === IDENTIFIER) {
            tt = t.peek();
            
            if (tt === COLON) {
                label = t.token.value;
                if (x.allLabels.has(label))
                    throw t.newSyntaxError("Duplicate label");
                t.get();
                n = new Node(t, { type: LABEL, label: label });
                n.statement = Statement(t, x.pushLabel(label).nest(NESTING_SHALLOW));
                n.target = (n.statement.type === LABEL) ? n.statement.target : n.statement;
                return n;
            }
        }

        
        
        n = new Node(t, { type: SEMICOLON });
        t.unget();
        n.expression = Expression(t, x);
        n.end = n.expression.end;
        break;
    }

    MagicalSemicolon(t);
    return n;
}
function Statement ( t , x ) { var i , label , n , n2 , p , c , ss , tt = t . get ( true ) , tt2 , x2 , x3 ; // Cases for statements ending in a right curly return early, avoiding the // common semicolon insertion magic after this switch. switch ( tt ) { case FUNCTION : // DECLARED_FORM extends funDecls of x, STATEMENT_FORM doesn't. return FunctionDefinition ( t , x , true , ( x . nesting !== NESTING_TOP ) ? STATEMENT_FORM : DECLARED_FORM ) ; case LEFT_CURLY : n = new Node ( t , blockInit ( ) ) ; Statements ( t , x . update ( { parentBlock : n } ) . pushTarget ( n ) . nest ( NESTING_SHALLOW ) , n ) ; t . mustMatch ( RIGHT_CURLY ) ; return n ; case IF : n = new Node ( t ) ; n . condition = HeadExpression ( t , x ) ; x2 = x . pushTarget ( n ) . nest ( NESTING_DEEP ) ; n . thenPart = Statement ( t , x2 ) ; n . elsePart = t . match ( ELSE ) ? Statement ( t , x2 ) : null ; return n ; case SWITCH : // This allows CASEs after a DEFAULT, which is in the standard. n = new Node ( t , { cases : [ ] , defaultIndex : - 1 } ) ; n . discriminant = HeadExpression ( t , x ) ; x2 = x . pushTarget ( n ) . nest ( NESTING_DEEP ) ; t . mustMatch ( LEFT_CURLY ) ; while ( ( tt = t . get ( ) ) !== RIGHT_CURLY ) { switch ( tt ) { case DEFAULT : if ( n . defaultIndex >= 0 ) throw t . newSyntaxError ( "More than one switch default" ) ; // FALL THROUGH case CASE : n2 = new Node ( t ) ; if ( tt === DEFAULT ) n . defaultIndex = n . cases . length ; else n2 . caseLabel = Expression ( t , x2 , COLON ) ; break ; default : throw t . newSyntaxError ( "Invalid switch case" ) ; } t . mustMatch ( COLON ) ; n2 . statements = new Node ( t , blockInit ( ) ) ; while ( ( tt = t . peek ( true ) ) !== CASE && tt !== DEFAULT && tt !== RIGHT_CURLY ) n2 . statements . push ( Statement ( t , x2 ) ) ; n . cases . push ( n2 ) ; } return n ; case FOR : n = new Node ( t , LOOP_INIT ) ; if ( t . match ( IDENTIFIER ) ) { if ( t . token . value === "each" ) n . isEach = true ; else t . unget ( ) ; } if ( ! x . parenFreeMode ) t . mustMatch ( LEFT_PAREN ) ; x2 = x . pushTarget ( n ) . nest ( NESTING_DEEP ) ; x3 = x . update ( { inForLoopInit : true } ) ; if ( ( tt = t . peek ( ) ) !== SEMICOLON ) { if ( tt === VAR || tt === CONST ) { t . get ( ) ; n2 = Variables ( t , x3 ) ; } else if ( tt === LET ) { t . get ( ) ; if ( t . peek ( ) === LEFT_PAREN ) { n2 = LetBlock ( t , x3 , false ) ; } else { // Let in for head, we need to add an implicit block // around the rest of the for. x3 . parentBlock = n ; n . varDecls = [ ] ; n2 = Variables ( t , x3 ) ; } } else { n2 = Expression ( t , x3 ) ; } } if ( n2 && t . match ( IN ) ) { n . type = FOR_IN ; n . object = Expression ( t , x3 ) ; if ( n2 . type === VAR || n2 . type === LET ) { c = n2 . children ; // Destructuring turns one decl into multiples, so either // there must be only one destructuring or only one // decl. if ( c . length !== 1 && n2 . destructurings . length !== 1 ) { throw new SyntaxError ( "Invalid for..in left-hand side" , t . filename , n2 . lineno ) ; } if ( n2 . destructurings . length > 0 ) { n . iterator = n2 . destructurings [ 0 ] ; } else { n . iterator = c [ 0 ] ; } n . varDecl = n2 ; } else { if ( n2 . type === ARRAY_INIT || n2 . type === OBJECT_INIT ) { n2 . destructuredNames = checkDestructuring ( t , x3 , n2 ) ; } n . iterator = n2 ; } } else { n . setup = n2 ; t . mustMatch ( SEMICOLON ) ; if ( n . isEach ) throw t . newSyntaxError ( "Invalid for each..in loop" ) ; n . condition = ( t . peek ( ) === SEMICOLON ) ? null : Expression ( t , x3 ) ; t . mustMatch ( SEMICOLON ) ; tt2 = t . peek ( ) ; n . update = ( x . parenFreeMode ? tt2 === LEFT_CURLY || definitions . isStatementStartCode [ tt2 ] : tt2 === RIGHT_PAREN ) ? null : Expression ( t , x3 ) ; } if ( ! x . parenFreeMode ) t . mustMatch ( RIGHT_PAREN ) ; n . body = Statement ( t , x2 ) ; return n ; case WHILE : n = new Node ( t , { isLoop : true } ) ; n . condition = HeadExpression ( t , x ) ; n . body = Statement ( t , x . pushTarget ( n ) . nest ( NESTING_DEEP ) ) ; return n ; case DO : n = new Node ( t , { isLoop : true } ) ; n . body = Statement ( t , x . pushTarget ( n ) . nest ( NESTING_DEEP ) ) ; t . mustMatch ( WHILE ) ; n . condition = HeadExpression ( t , x ) ; if ( ! x . ecmaStrictMode ) { // <script language="JavaScript"> (without version hints) may need // automatic semicolon insertion without a newline after do-while. // See http://bugzilla.mozilla.org/show_bug.cgi?id=238945. t . match ( SEMICOLON ) ; return n ; } break ; case BREAK : case CONTINUE : n = new Node ( t ) ; // handle the |foo: break foo;| corner case x2 = x . pushTarget ( n ) ; if ( t . peekOnSameLine ( ) === IDENTIFIER ) { t . get ( ) ; n . label = t . token . value ; } n . target = n . label ? x2 . labeledTargets . find ( function ( target ) { return target . labels . has ( n . label ) } ) : x2 . defaultTarget ; if ( ! n . target ) throw t . newSyntaxError ( "Invalid " + ( ( tt === BREAK ) ? "break" : "continue" ) ) ; if ( ! n . target . isLoop && tt === CONTINUE ) throw t . newSyntaxError ( "Invalid continue" ) ; break ; case TRY : n = new Node ( t , { catchClauses : [ ] } ) ; n . tryBlock = Block ( t , x ) ; while ( t . match ( CATCH ) ) { n2 = new Node ( t ) ; p = MaybeLeftParen ( t , x ) ; switch ( t . get ( ) ) { case LEFT_BRACKET : case LEFT_CURLY : // Destructured catch identifiers. t . unget ( ) ; n2 . varName = DestructuringExpression ( t , x , true ) ; break ; case IDENTIFIER : n2 . varName = t . token . value ; break ; default : throw t . newSyntaxError ( "missing identifier in catch" ) ; break ; } if ( t . match ( IF ) ) { if ( x . ecma3OnlyMode ) throw t . newSyntaxError ( "Illegal catch guard" ) ; if ( n . catchClauses . length && ! n . catchClauses . top ( ) . guard ) throw t . newSyntaxError ( "Guarded catch after unguarded" ) ; n2 . guard = Expression ( t , x ) ; } MaybeRightParen ( t , p ) ; n2 . block = Block ( t , x ) ; n . catchClauses . push ( n2 ) ; } if ( t . match ( FINALLY ) ) n . finallyBlock = Block ( t , x ) ; if ( ! n . catchClauses . length && ! n . finallyBlock ) throw t . newSyntaxError ( "Invalid try statement" ) ; return n ; case CATCH : case FINALLY : throw t . newSyntaxError ( definitions . tokens [ tt ] + " without preceding try" ) ; case THROW : n = new Node ( t ) ; n . exception = Expression ( t , x ) ; break ; case RETURN : n = ReturnOrYield ( t , x ) ; break ; case WITH : n = new Node ( t ) ; n . object = HeadExpression ( t , x ) ; n . body = Statement ( t , x . pushTarget ( n ) . nest ( NESTING_DEEP ) ) ; return n ; case VAR : case CONST : n = Variables ( t , x ) ; break ; case LET : if ( t . peek ( ) === LEFT_PAREN ) n = LetBlock ( t , x , true ) ; else n = Variables ( t , x ) ; break ; case DEBUGGER : n = new Node ( t ) ; break ; case NEWLINE : case SEMICOLON : n = new Node ( t , { type : SEMICOLON } ) ; n . expression = null ; return n ; default : if ( tt === IDENTIFIER ) { tt = t . peek ( ) ; // Labeled statement. if ( tt === COLON ) { label = t . token . value ; if ( x . allLabels . has ( label ) ) throw t . newSyntaxError ( "Duplicate label" ) ; t . get ( ) ; n = new Node ( t , { type : LABEL , label : label } ) ; n . statement = Statement ( t , x . pushLabel ( label ) . nest ( NESTING_SHALLOW ) ) ; n . target = ( n . statement . type === LABEL ) ? n . statement . target : n . statement ; return n ; } } // Expression statement. // We unget the current token to parse the expression as a whole. n = new Node ( t , { type : SEMICOLON } ) ; t . unget ( ) ; n . expression = Expression ( t , x ) ; n . end = n . expression . end ; break ; } MagicalSemicolon ( t ) ; return n ; }
/*
Statement :: (tokenizer, compiler context) -> node

Parses a Statement.
/ * Statement :: ( tokenizer compiler context ) - > node