/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>

#include <cstring>

#include "qmljsengine_p.h"
#include "qmljslexer_p.h"
#include "qmljsast_p.h"
#include "qmljsmemorypool_p.h"



#include "qmljsparser_p.h"
#include <QtCore/qvarlengtharray.h>

//
// This file is automatically generated from qmljs.g.
// Changes will be lost.
//

namespace QbsQmlJS {

void Parser::reallocateStack()
{
    if (! stack_size)
        stack_size = 128;
    else
        stack_size <<= 1;

    sym_stack = reinterpret_cast<Value*> (realloc(sym_stack, stack_size * sizeof(Value)));
    state_stack = reinterpret_cast<int*> (realloc(state_stack, stack_size * sizeof(int)));
    location_stack = reinterpret_cast<AST::SourceLocation*> (realloc(location_stack, stack_size * sizeof(AST::SourceLocation)));
    string_stack = reinterpret_cast<QStringRef*> (realloc(
                   static_cast<void *>(string_stack), stack_size * sizeof(QStringRef)));
}

Parser::Parser(Engine *engine):
    driver(engine),
    pool(engine->pool()),
    tos(0),
    stack_size(0),
    sym_stack(nullptr),
    state_stack(nullptr),
    location_stack(nullptr),
    string_stack(nullptr),
    program(nullptr),
    first_token(nullptr),
    last_token(nullptr)
{
}

Parser::~Parser()
{
    if (stack_size) {
        free(sym_stack);
        free(state_stack);
        free(location_stack);
        free(string_stack);
    }
}

static inline AST::SourceLocation location(Lexer *lexer)
{
    AST::SourceLocation loc;
    loc.offset = lexer->tokenOffset();
    loc.length = lexer->tokenLength();
    loc.startLine = lexer->tokenStartLine();
    loc.startColumn = lexer->tokenStartColumn();
    return loc;
}

AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr)
{
    QVarLengthArray<QStringRef, 4> nameIds;
    QVarLengthArray<AST::SourceLocation, 4> locations;

    AST::ExpressionNode *it = expr;
    while (const auto m = AST::cast<AST::FieldMemberExpression *>(it)) {
        nameIds.append(m->name);
        locations.append(m->identifierToken);
        it = m->base;
    }

    if (const auto idExpr = AST::cast<AST::IdentifierExpression *>(it)) {
        const auto q = new (pool) AST::UiQualifiedId(idExpr->name);
        q->identifierToken = idExpr->identifierToken;

        AST::UiQualifiedId *currentId = q;
        for (int i = nameIds.size() - 1; i != -1; --i) {
            currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]);
            currentId->identifierToken = locations[i];
        }

        return currentId->finish();
    }

    return nullptr;
}

bool Parser::parse(int startToken)
{
    Lexer *lexer = driver->lexer();
    bool hadErrors = false;
    int yytoken = -1;
    int action = 0;

    token_buffer[0].token = startToken;
    first_token = &token_buffer[0];
    if (startToken == T_FEED_JS_PROGRAM) {
        Directives ignoreDirectives;
        Directives *directives = driver->directives();
        if (!directives)
            directives = &ignoreDirectives;
        lexer->scanDirectives(directives);
        token_buffer[1].token = lexer->tokenKind();
        token_buffer[1].dval = lexer->tokenValue();
        token_buffer[1].loc = location(lexer);
        token_buffer[1].spell = lexer->tokenSpell();
        last_token = &token_buffer[2];
    } else {
        last_token = &token_buffer[1];
    }

    tos = -1;
    program = nullptr;

    do {
        if (++tos == stack_size)
            reallocateStack();

        state_stack[tos] = action;

    _Lcheck_token:
        if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) {
            yyprevlloc = yylloc;

            if (first_token == last_token) {
                yytoken = lexer->lex();
                yylval = lexer->tokenValue();
                yytokenspell = lexer->tokenSpell();
                yylloc = location(lexer);
            } else {
                yytoken = first_token->token;
                yylval = first_token->dval;
                yytokenspell = first_token->spell;
                yylloc = first_token->loc;
                ++first_token;
            }
        }

        action = t_action(action, yytoken);
        if (action > 0) {
            if (action != ACCEPT_STATE) {
                yytoken = -1;
                sym(1).dval = yylval;
                stringRef(1) = yytokenspell;
                loc(1) = yylloc;
            } else {
              --tos;
              return ! hadErrors;
            }
        } else if (action < 0) {
          const int r = -action - 1;
          tos -= rhs[r];

          switch (r) {

case 0: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 1: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 2: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 3: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 4: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 5: {
  sym(1).Node = sym(2).Node;
  program = sym(1).Node;
} break;

case 6: {
  sym(1).UiProgram = new (pool) AST::UiProgram(sym(1).UiImportList,
        sym(2).UiObjectMemberList->finish());
} break;

case 8: {
    sym(1).Node = sym(1).UiImportList->finish();
} break;

case 9: {
    sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImport);
} break;

case 10: {
    sym(1).Node = new (pool) AST::UiImportList(sym(1).UiImportList, sym(2).UiImport);
} break;

case 13: {
    sym(1).UiImport->semicolonToken = loc(2);
} break;

case 15: {
    sym(1).UiImport->versionToken = loc(2);
    sym(1).UiImport->semicolonToken = loc(3);
} break;

case 17: {
    sym(1).UiImport->versionToken = loc(2);
    sym(1).UiImport->asToken = loc(3);
    sym(1).UiImport->importIdToken = loc(4);
    sym(1).UiImport->importId = stringRef(4);
    sym(1).UiImport->semicolonToken = loc(5);
} break;

case 19: {
    sym(1).UiImport->asToken = loc(2);
    sym(1).UiImport->importIdToken = loc(3);
    sym(1).UiImport->importId = stringRef(3);
    sym(1).UiImport->semicolonToken = loc(4);
} break;

case 20: {
    AST::UiImport *node = nullptr;

    if (const auto importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) {
        node = new (pool) AST::UiImport(importIdLiteral->value);
        node->fileNameToken = loc(2);
    } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
        node = new (pool) AST::UiImport(qualifiedId);
        node->fileNameToken = loc(2);
    }

    sym(1).Node = node;

    if (node) {
        node->importToken = loc(1);
    } else {
       diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
         QStringLiteral("Expected a qualified name id or a string literal")));

        return false; // ### remove me
    }
} break;

case 21: {
    sym(1).Node = nullptr;
} break;

case 22: {
    sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
} break;

case 23: {
    sym(1).Node = new (pool) AST::UiObjectMemberList(sym(1).UiObjectMember);
} break;

case 24: {
    const auto node = new (pool) AST:: UiObjectMemberList(
        sym(1).UiObjectMemberList, sym(2).UiObjectMember);
    sym(1).Node = node;
} break;

case 25: {
    sym(1).Node = new (pool) AST::UiArrayMemberList(sym(1).UiObjectMember);
} break;

case 26: {
    const auto node = new (pool) AST::UiArrayMemberList(
        sym(1).UiArrayMemberList, sym(3).UiObjectMember);
    node->commaToken = loc(2);
    sym(1).Node = node;
} break;

case 27: {
    const auto node = new (pool) AST::UiObjectInitializer(nullptr);
    node->lbraceToken = loc(1);
    node->rbraceToken = loc(2);
    sym(1).Node = node;
}   break;

case 28: {
    const auto node = new (pool) AST::UiObjectInitializer(sym(2).UiObjectMemberList->finish());
    node->lbraceToken = loc(1);
    node->rbraceToken = loc(3);
    sym(1).Node = node;
}   break;

case 29: {
    const auto node = new (pool) AST::UiObjectDefinition(sym(1).UiQualifiedId,
        sym(2).UiObjectInitializer);
    sym(1).Node = node;
}   break;

case 31: {
    const auto node = new (pool) AST::UiArrayBinding(
        sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish());
    node->colonToken = loc(2);
    node->lbracketToken = loc(3);
    node->rbracketToken = loc(5);
    sym(1).Node = node;
}   break;

case 32: {
    const auto node = new (pool) AST::UiObjectBinding(
      sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer);
    node->colonToken = loc(2);
    sym(1).Node = node;
} break;

case 33: {
    const auto node = new (pool) AST::UiObjectBinding(
      sym(3).UiQualifiedId, sym(1).UiQualifiedId, sym(4).UiObjectInitializer);
    node->colonToken = loc(2);
    node->hasOnToken = true;
    sym(1).Node = node;
} break;

case 41:
{
    const auto node = new (pool) AST::UiScriptBinding(
        sym(1).UiQualifiedId, sym(3).Statement);
    node->colonToken = loc(2);
    sym(1).Node = node;
}   break;

case 45: {
  sym(1).Node = nullptr;
} break;

case 46: {
  sym(1).Node = sym(1).UiParameterList->finish ();
} break;

case 47: {
  const auto node = new (pool) AST::UiParameterList(stringRef(1), stringRef(2));
  node->propertyTypeToken = loc(1);
  node->identifierToken = loc(2);
  sym(1).Node = node;
} break;

case 48: {
  const auto node = new (pool) AST::UiParameterList(sym(1).UiParameterList, stringRef(3), stringRef(4));
  node->commaToken = loc(2);
  node->identifierToken = loc(4);
  sym(1).Node = node;
} break;

case 50: {
    const auto node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2));
    node->type = AST::UiPublicMember::Signal;
    node->propertyToken = loc(1);
    node->typeToken = loc(2);
    node->identifierToken = loc(2);
    node->parameters = sym(4).UiParameterList;
    node->semicolonToken = loc(6);
    sym(1).Node = node;
}   break;

case 52: {
    const auto node = new (pool) AST::UiPublicMember(QStringRef(), stringRef(2));
    node->type = AST::UiPublicMember::Signal;
    node->propertyToken = loc(1);
    node->typeToken = loc(2);
    node->identifierToken = loc(2);
    node->semicolonToken = loc(3);
    sym(1).Node = node;
}   break;

case 54: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6));
    node->typeModifier = stringRef(2);
    node->propertyToken = loc(1);
    node->typeModifierToken = loc(2);
    node->typeToken = loc(4);
    node->identifierToken = loc(6);
    node->semicolonToken = loc(7);
    sym(1).Node = node;
}   break;

case 56: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3));
    node->propertyToken = loc(1);
    node->typeToken = loc(2);
    node->identifierToken = loc(3);
    node->semicolonToken = loc(4);
    sym(1).Node = node;
}   break;

case 58: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4));
    node->isDefaultMember = true;
    node->defaultToken = loc(1);
    node->propertyToken = loc(2);
    node->typeToken = loc(3);
    node->identifierToken = loc(4);
    node->semicolonToken = loc(5);
    sym(1).Node = node;
}   break;

case 59: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3),
        sym(5).Statement);
    node->propertyToken = loc(1);
    node->typeToken = loc(2);
    node->identifierToken = loc(3);
    node->colonToken = loc(4);
    sym(1).Node = node;
}   break;

case 60: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4),
        sym(6).Statement);
    node->isReadonlyMember = true;
    node->readonlyToken = loc(1);
    node->propertyToken = loc(2);
    node->typeToken = loc(3);
    node->identifierToken = loc(4);
    node->colonToken = loc(5);
    sym(1).Node = node;
}   break;

case 61: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(3), stringRef(4),
        sym(6).Statement);
    node->isDefaultMember = true;
    node->defaultToken = loc(1);
    node->propertyToken = loc(2);
    node->typeToken = loc(3);
    node->identifierToken = loc(4);
    node->colonToken = loc(5);
    sym(1).Node = node;
}   break;

case 62: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(4), stringRef(6));
    node->typeModifier = stringRef(2);
    node->propertyToken = loc(1);
    node->typeModifierToken = loc(2);
    node->typeToken = loc(4);
    node->identifierToken = loc(6);
    node->semicolonToken = loc(7); // insert a fake ';' before ':'

    const auto propertyName = new (pool) AST::UiQualifiedId(stringRef(6));
    propertyName->identifierToken = loc(6);
    propertyName->next = nullptr;

    const auto binding = new (pool) AST::UiArrayBinding(
        propertyName, sym(9).UiArrayMemberList->finish());
    binding->colonToken = loc(7);
    binding->lbracketToken = loc(8);
    binding->rbracketToken = loc(10);

    node->binding = binding;

    sym(1).Node = node;
}   break;

case 63: {
    const auto node = new (pool) AST::UiPublicMember(stringRef(2), stringRef(3));
    node->propertyToken = loc(1);
    node->typeToken = loc(2);
    node->identifierToken = loc(3);
    node->semicolonToken = loc(4); // insert a fake ';' before ':'

    const auto propertyName = new (pool) AST::UiQualifiedId(stringRef(3));
    propertyName->identifierToken = loc(3);
    propertyName->next = nullptr;

    const auto binding = new (pool) AST::UiObjectBinding(
      propertyName, sym(5).UiQualifiedId, sym(6).UiObjectInitializer);
    binding->colonToken = loc(4);

    node->binding = binding;

    sym(1).Node = node;
}   break;

case 64: {
    sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
}   break;

case 65: {
    sym(1).Node = new (pool) AST::UiSourceElement(sym(1).Node);
}   break;

case 71: {
  const auto node = new (pool) AST::ThisExpression();
  node->thisToken = loc(1);
  sym(1).Node = node;
} break;

case 72: {
  const auto node = new (pool) AST::IdentifierExpression(stringRef(1));
  node->identifierToken = loc(1);
  sym(1).Node = node;
} break;

case 73: {
  const auto node = new (pool) AST::NullExpression();
  node->nullToken = loc(1);
  sym(1).Node = node;
} break;

case 74: {
  const auto node = new (pool) AST::TrueLiteral();
  node->trueToken = loc(1);
  sym(1).Node = node;
} break;

case 75: {
  const auto node = new (pool) AST::FalseLiteral();
  node->falseToken = loc(1);
  sym(1).Node = node;
} break;

case 76: {
  const auto node = new (pool) AST::NumericLiteral(sym(1).dval);
  node->literalToken = loc(1);
  sym(1).Node = node;
} break;
case 77:
case 78: {
  const auto node = new (pool) AST::StringLiteral(stringRef(1));
  node->literalToken = loc(1);
  sym(1).Node = node;
} break;

case 79: {
  bool rx = lexer->scanRegExp(Lexer::NoPrefix);
  if (!rx) {
    diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
    return false; // ### remove me
  }

  loc(1).length = lexer->tokenLength();
  yylloc = loc(1); // adjust the location of the current token

  const auto node = new (pool) AST::RegExpLiteral(
    driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
  node->literalToken = loc(1);
  sym(1).Node = node;
} break;

case 80: {
  bool rx = lexer->scanRegExp(Lexer::EqualPrefix);
  if (!rx) {
    diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
    return false;
  }

  loc(1).length = lexer->tokenLength();
  yylloc = loc(1); // adjust the location of the current token

  const auto node = new (pool) AST::RegExpLiteral(
    driver->newStringRef(lexer->regExpPattern()), lexer->regExpFlags());
  node->literalToken = loc(1);
  sym(1).Node = node;
} break;

case 81: {
  const auto node = new (pool) AST::ArrayLiteral(static_cast<AST::Elision *>(nullptr));
  node->lbracketToken = loc(1);
  node->rbracketToken = loc(2);
  sym(1).Node = node;
} break;

case 82: {
  const auto node = new (pool) AST::ArrayLiteral(sym(2).Elision->finish());
  node->lbracketToken = loc(1);
  node->rbracketToken = loc(3);
  sym(1).Node = node;
} break;

case 83: {
  const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish ());
  node->lbracketToken = loc(1);
  node->rbracketToken = loc(3);
  sym(1).Node = node;
} break;

case 84: {
  const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (), nullptr);
  node->lbracketToken = loc(1);
  node->commaToken = loc(3);
  node->rbracketToken = loc(4);
  sym(1).Node = node;
} break;

case 85: {
  const auto node = new (pool) AST::ArrayLiteral(sym(2).ElementList->finish (),
    sym(4).Elision->finish());
  node->lbracketToken = loc(1);
  node->commaToken = loc(3);
  node->rbracketToken = loc(5);
  sym(1).Node = node;
} break;

case 86: {
  AST::ObjectLiteral *node = nullptr;
  if (sym(2).Node)
    node = new (pool) AST::ObjectLiteral(
        sym(2).PropertyNameAndValueList->finish ());
  else
    node = new (pool) AST::ObjectLiteral();
  node->lbraceToken = loc(1);
  node->rbraceToken = loc(3);
  sym(1).Node = node;
} break;

case 87: {
  const auto node = new (pool) AST::ObjectLiteral(
    sym(2).PropertyNameAndValueList->finish ());
  node->lbraceToken = loc(1);
  node->rbraceToken = loc(4);
  sym(1).Node = node;
} break;

case 88: {
  const auto node = new (pool) AST::NestedExpression(sym(2).Expression);
  node->lparenToken = loc(1);
  node->rparenToken = loc(3);
  sym(1).Node = node;
} break;

case 89: {
  if (const auto *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) {
    diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken,
      QStringLiteral("Ignored annotation")));

    sym(1).Expression = mem->base;
  }

  if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) {
    sym(1).UiQualifiedId = qualifiedId;
  } else {
    sym(1).UiQualifiedId = nullptr;

    diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1),
      QStringLiteral("Expected a qualified name id")));

    return false; // ### recover
  }
} break;

case 90: {
  sym(1).Node = new (pool) AST::ElementList(nullptr, sym(1).Expression);
} break;

case 91: {
  sym(1).Node = new (pool) AST::ElementList(sym(1).Elision->finish(), sym(2).Expression);
} break;

case 92: {
 const auto node = new (pool) AST::ElementList(sym(1).ElementList, nullptr, sym(3).Expression);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 93: {
  const auto node = new (pool) AST::ElementList(sym(1).ElementList, sym(3).Elision->finish(),
    sym(4).Expression);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 94: {
  const auto node = new (pool) AST::Elision();
  node->commaToken = loc(1);
  sym(1).Node = node;
} break;

case 95: {
  const auto node = new (pool) AST::Elision(sym(1).Elision);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 96: {
  const auto node = new (pool) AST::PropertyNameAndValueList(
      sym(1).PropertyName, sym(3).Expression);
  node->colonToken = loc(2);
  sym(1).Node = node;
} break;

case 97: {
  const auto node = new (pool) AST::PropertyNameAndValueList(
      sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression);
  node->commaToken = loc(2);
  node->colonToken = loc(4);
  sym(1).Node = node;
} break;

case 98: {
  const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1));
  node->propertyNameToken = loc(1);
  sym(1).Node = node;
} break;
case 99:
case 100: {
  const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1));
  node->propertyNameToken = loc(1);
  sym(1).Node = node;
} break;

case 101: {
  const auto node = new (pool) AST::StringLiteralPropertyName(stringRef(1));
  node->propertyNameToken = loc(1);
  sym(1).Node = node;
} break;

case 102: {
  const auto node = new (pool) AST::NumericLiteralPropertyName(sym(1).dval);
  node->propertyNameToken = loc(1);
  sym(1).Node = node;
} break;

case 103: {
  const auto node = new (pool) AST::IdentifierPropertyName(stringRef(1));
  node->propertyNameToken = loc(1);
  sym(1).Node = node;
} break;

case 139: {
  const auto node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
  node->lbracketToken = loc(2);
  node->rbracketToken = loc(4);
  sym(1).Node = node;
} break;

case 140: {
  const auto node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
  node->dotToken = loc(2);
  node->identifierToken = loc(3);
  sym(1).Node = node;
} break;

case 141: {
  const auto node = new (pool) AST::NewMemberExpression(sym(2).Expression, sym(4).ArgumentList);
  node->newToken = loc(1);
  node->lparenToken = loc(3);
  node->rparenToken = loc(5);
  sym(1).Node = node;
} break;

case 143: {
  const auto node = new (pool) AST::NewExpression(sym(2).Expression);
  node->newToken = loc(1);
  sym(1).Node = node;
} break;

case 144: {
  const auto node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 145: {
  const auto node = new (pool) AST::CallExpression(sym(1).Expression, sym(3).ArgumentList);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 146: {
  const auto node = new (pool) AST::ArrayMemberExpression(sym(1).Expression, sym(3).Expression);
  node->lbracketToken = loc(2);
  node->rbracketToken = loc(4);
  sym(1).Node = node;
} break;

case 147: {
  const auto node = new (pool) AST::FieldMemberExpression(sym(1).Expression, stringRef(3));
  node->dotToken = loc(2);
  node->identifierToken = loc(3);
  sym(1).Node = node;
} break;

case 148: {
  sym(1).Node = nullptr;
} break;

case 149: {
  sym(1).Node = sym(1).ArgumentList->finish();
} break;

case 150: {
  sym(1).Node = new (pool) AST::ArgumentList(sym(1).Expression);
} break;

case 151: {
  const auto node = new (pool) AST::ArgumentList(sym(1).ArgumentList, sym(3).Expression);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 155: {
  const auto node = new (pool) AST::PostIncrementExpression(sym(1).Expression);
  node->incrementToken = loc(2);
  sym(1).Node = node;
} break;

case 156: {
  const auto node = new (pool) AST::PostDecrementExpression(sym(1).Expression);
  node->decrementToken = loc(2);
  sym(1).Node = node;
} break;

case 158: {
  const auto node = new (pool) AST::DeleteExpression(sym(2).Expression);
  node->deleteToken = loc(1);
  sym(1).Node = node;
} break;

case 159: {
  const auto node = new (pool) AST::VoidExpression(sym(2).Expression);
  node->voidToken = loc(1);
  sym(1).Node = node;
} break;

case 160: {
  const auto node = new (pool) AST::TypeOfExpression(sym(2).Expression);
  node->typeofToken = loc(1);
  sym(1).Node = node;
} break;

case 161: {
  const auto node = new (pool) AST::PreIncrementExpression(sym(2).Expression);
  node->incrementToken = loc(1);
  sym(1).Node = node;
} break;

case 162: {
  const auto node = new (pool) AST::PreDecrementExpression(sym(2).Expression);
  node->decrementToken = loc(1);
  sym(1).Node = node;
} break;

case 163: {
  const auto node = new (pool) AST::UnaryPlusExpression(sym(2).Expression);
  node->plusToken = loc(1);
  sym(1).Node = node;
} break;

case 164: {
  const auto node = new (pool) AST::UnaryMinusExpression(sym(2).Expression);
  node->minusToken = loc(1);
  sym(1).Node = node;
} break;

case 165: {
  const auto node = new (pool) AST::TildeExpression(sym(2).Expression);
  node->tildeToken = loc(1);
  sym(1).Node = node;
} break;

case 166: {
  const auto node = new (pool) AST::NotExpression(sym(2).Expression);
  node->notToken = loc(1);
  sym(1).Node = node;
} break;

case 168: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Mul, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 169: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Div, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 170: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Mod, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 172: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Add, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 173: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Sub, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 175: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::LShift, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 176: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::RShift, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 177: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::URShift, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 179: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Lt, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 180: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Gt, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 181: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Le, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 182: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Ge, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 183: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::InstanceOf, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 184: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::In, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 186: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Lt, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 187: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Gt, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 188: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Le, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 189: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
   QSOperator::Ge, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 190: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::InstanceOf, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 192: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Equal, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 193: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::NotEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 194: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::StrictEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 195: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::StrictNotEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 197: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Equal, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 198: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::NotEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 199: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::StrictEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 200: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::StrictNotEqual, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 202: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitAnd, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 204: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitAnd, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 206: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitXor, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 208: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitXor, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 210: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitOr, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 212: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::BitOr, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 214: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::And, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 216: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::And, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 218: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Or, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 220: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    QSOperator::Or, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 222: {
  const auto node = new (pool) AST::ConditionalExpression(sym(1).Expression,
    sym(3).Expression, sym(5).Expression);
  node->questionToken = loc(2);
  node->colonToken = loc(4);
  sym(1).Node = node;
} break;

case 224: {
  const auto node = new (pool) AST::ConditionalExpression(sym(1).Expression,
    sym(3).Expression, sym(5).Expression);
  node->questionToken = loc(2);
  node->colonToken = loc(4);
  sym(1).Node = node;
} break;

case 226: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    sym(2).ival, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 228: {
  const auto node = new (pool) AST::BinaryExpression(sym(1).Expression,
    sym(2).ival, sym(3).Expression);
  node->operatorToken = loc(2);
  sym(1).Node = node;
} break;

case 229: {
  sym(1).ival = QSOperator::Assign;
} break;

case 230: {
  sym(1).ival = QSOperator::InplaceMul;
} break;

case 231: {
  sym(1).ival = QSOperator::InplaceDiv;
} break;

case 232: {
  sym(1).ival = QSOperator::InplaceMod;
} break;

case 233: {
  sym(1).ival = QSOperator::InplaceAdd;
} break;

case 234: {
  sym(1).ival = QSOperator::InplaceSub;
} break;

case 235: {
  sym(1).ival = QSOperator::InplaceLeftShift;
} break;

case 236: {
  sym(1).ival = QSOperator::InplaceRightShift;
} break;

case 237: {
  sym(1).ival = QSOperator::InplaceURightShift;
} break;

case 238: {
  sym(1).ival = QSOperator::InplaceAnd;
} break;

case 239: {
  sym(1).ival = QSOperator::InplaceXor;
} break;

case 240: {
  sym(1).ival = QSOperator::InplaceOr;
} break;

case 242: {
  const auto node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 243: {
  sym(1).Node = nullptr;
} break;

case 246: {
  const auto node = new (pool) AST::Expression(sym(1).Expression, sym(3).Expression);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 247: {
  sym(1).Node = nullptr;
} break;

case 264: {
  const auto node = new (pool) AST::Block(sym(2).StatementList);
  node->lbraceToken = loc(1);
  node->rbraceToken = loc(3);
  sym(1).Node = node;
} break;

case 265: {
  sym(1).Node = new (pool) AST::StatementList(sym(1).Statement);
} break;

case 266: {
  sym(1).Node = new (pool) AST::StatementList(sym(1).StatementList, sym(2).Statement);
} break;

case 267: {
  sym(1).Node = nullptr;
} break;

case 268: {
  sym(1).Node = sym(1).StatementList->finish ();
} break;

case 270: {
  const auto node = new (pool) AST::VariableStatement(
     sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST));
  node->declarationKindToken = loc(1);
  node->semicolonToken = loc(3);
  sym(1).Node = node;
} break;

case 271: {
  sym(1).ival = T_CONST;
} break;

case 272: {
  sym(1).ival = T_VAR;
} break;

case 273: {
  sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
} break;

case 274: {
  const auto node = new (pool) AST::VariableDeclarationList(
    sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
  node->commaToken = loc(2);
  sym(1).Node = node;
} break;

case 275: {
  sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclaration);
} break;

case 276: {
  sym(1).Node = new (pool) AST::VariableDeclarationList(sym(1).VariableDeclarationList, sym(3).VariableDeclaration);
} break;

case 277: {
  const auto node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
  node->identifierToken = loc(1);
  sym(1).Node = node;
} break;

case 278: {
  const auto node = new (pool) AST::VariableDeclaration(stringRef(1), sym(2).Expression);
  node->identifierToken = loc(1);
  sym(1).Node = node;
} break;

case 279: {
  // ### TODO: AST for initializer
  sym(1) = sym(2);
} break;

case 280: {
  sym(1).Node = nullptr;
} break;

case 282: {
  // ### TODO: AST for initializer
  sym(1) = sym(2);
} break;

case 283: {
  sym(1).Node = nullptr;
} break;

case 285: {
  const auto node = new (pool) AST::EmptyStatement();
  node->semicolonToken = loc(1);
  sym(1).Node = node;
} break;

case 287: {
  const auto node = new (pool) AST::ExpressionStatement(sym(1).Expression);
  node->semicolonToken = loc(2);
  sym(1).Node = node;
} break;

case 288: {
  const auto node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement, sym(7).Statement);
  node->ifToken = loc(1);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  node->elseToken = loc(6);
  sym(1).Node = node;
} break;

case 289: {
  const auto node = new (pool) AST::IfStatement(sym(3).Expression, sym(5).Statement);
  node->ifToken = loc(1);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 291: {
  const auto node = new (pool) AST::DoWhileStatement(sym(2).Statement, sym(5).Expression);
  node->doToken = loc(1);
  node->whileToken = loc(3);
  node->lparenToken = loc(4);
  node->rparenToken = loc(6);
  node->semicolonToken = loc(7);
  sym(1).Node = node;
} break;

case 292: {
  const auto node = new (pool) AST::WhileStatement(sym(3).Expression, sym(5).Statement);
  node->whileToken = loc(1);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 293: {
  const auto node = new (pool) AST::ForStatement(sym(3).Expression,
    sym(5).Expression, sym(7).Expression, sym(9).Statement);
  node->forToken = loc(1);
  node->lparenToken = loc(2);
  node->firstSemicolonToken = loc(4);
  node->secondSemicolonToken = loc(6);
  node->rparenToken = loc(8);
  sym(1).Node = node;
} break;

case 294: {
  const auto node = new (pool) AST::LocalForStatement(
     sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression,
     sym(8).Expression, sym(10).Statement);
  node->forToken = loc(1);
  node->lparenToken = loc(2);
  node->varToken = loc(3);
  node->firstSemicolonToken = loc(5);
  node->secondSemicolonToken = loc(7);
  node->rparenToken = loc(9);
  sym(1).Node = node;
} break;

case 295: {
  const auto node = new (pool) AST::ForEachStatement(sym(3).Expression,
    sym(5).Expression, sym(7).Statement);
  node->forToken = loc(1);
  node->lparenToken = loc(2);
  node->inToken = loc(4);
  node->rparenToken = loc(6);
  sym(1).Node = node;
} break;

case 296: {
  const auto node = new (pool) AST::LocalForEachStatement(
    sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement);
  node->forToken = loc(1);
  node->lparenToken = loc(2);
  node->varToken = loc(3);
  node->inToken = loc(5);
  node->rparenToken = loc(7);
  sym(1).Node = node;
} break;

case 298: {
  const auto node = new (pool) AST::ContinueStatement();
  node->continueToken = loc(1);
  node->semicolonToken = loc(2);
  sym(1).Node = node;
} break;

case 300: {
  const auto node = new (pool) AST::ContinueStatement(stringRef(2));
  node->continueToken = loc(1);
  node->identifierToken = loc(2);
  node->semicolonToken = loc(3);
  sym(1).Node = node;
} break;

case 302: {
  const auto node = new (pool) AST::BreakStatement(QStringRef());
  node->breakToken = loc(1);
  node->semicolonToken = loc(2);
  sym(1).Node = node;
} break;

case 304: {
  const auto node = new (pool) AST::BreakStatement(stringRef(2));
  node->breakToken = loc(1);
  node->identifierToken = loc(2);
  node->semicolonToken = loc(3);
  sym(1).Node = node;
} break;

case 306: {
  const auto node = new (pool) AST::ReturnStatement(sym(2).Expression);
  node->returnToken = loc(1);
  node->semicolonToken = loc(3);
  sym(1).Node = node;
} break;

case 307: {
  const auto node = new (pool) AST::WithStatement(sym(3).Expression, sym(5).Statement);
  node->withToken = loc(1);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 308: {
  const auto node = new (pool) AST::SwitchStatement(sym(3).Expression, sym(5).CaseBlock);
  node->switchToken = loc(1);
  node->lparenToken = loc(2);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 309: {
  const auto node = new (pool) AST::CaseBlock(sym(2).CaseClauses);
  node->lbraceToken = loc(1);
  node->rbraceToken = loc(3);
  sym(1).Node = node;
} break;

case 310: {
  const auto node = new (pool) AST::CaseBlock(sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses);
  node->lbraceToken = loc(1);
  node->rbraceToken = loc(5);
  sym(1).Node = node;
} break;

case 311: {
  sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClause);
} break;

case 312: {
  sym(1).Node = new (pool) AST::CaseClauses(sym(1).CaseClauses, sym(2).CaseClause);
} break;

case 313: {
  sym(1).Node = nullptr;
} break;

case 314: {
  sym(1).Node = sym(1).CaseClauses->finish ();
} break;

case 315: {
  const auto node = new (pool) AST::CaseClause(sym(2).Expression, sym(4).StatementList);
  node->caseToken = loc(1);
  node->colonToken = loc(3);
  sym(1).Node = node;
} break;

case 316: {
  const auto node = new (pool) AST::DefaultClause(sym(3).StatementList);
  node->defaultToken = loc(1);
  node->colonToken = loc(2);
  sym(1).Node = node;
} break;
case 317:
case 318: {
  const auto node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
  node->identifierToken = loc(1);
  node->colonToken = loc(2);
  sym(1).Node = node;
} break;

case 319: {
  const auto node = new (pool) AST::LabelledStatement(stringRef(1), sym(3).Statement);
  node->identifierToken = loc(1);
  node->colonToken = loc(2);
  sym(1).Node = node;
} break;

case 321: {
  const auto node = new (pool) AST::ThrowStatement(sym(2).Expression);
  node->throwToken = loc(1);
  node->semicolonToken = loc(3);
  sym(1).Node = node;
} break;

case 322: {
  const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch);
  node->tryToken = loc(1);
  sym(1).Node = node;
} break;

case 323: {
  const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Finally);
  node->tryToken = loc(1);
  sym(1).Node = node;
} break;

case 324: {
  const auto node = new (pool) AST::TryStatement(sym(2).Statement, sym(3).Catch, sym(4).Finally);
  node->tryToken = loc(1);
  sym(1).Node = node;
} break;

case 325: {
  const auto node = new (pool) AST::Catch(stringRef(3), sym(5).Block);
  node->catchToken = loc(1);
  node->lparenToken = loc(2);
  node->identifierToken = loc(3);
  node->rparenToken = loc(4);
  sym(1).Node = node;
} break;

case 326: {
  const auto node = new (pool) AST::Finally(sym(2).Block);
  node->finallyToken = loc(1);
  sym(1).Node = node;
} break;

case 328: {
  const auto node = new (pool) AST::DebuggerStatement();
  node->debuggerToken = loc(1);
  node->semicolonToken = loc(2);
  sym(1).Node = node;
} break;

case 329: {
  const auto node = new (pool) AST::FunctionDeclaration(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
  node->functionToken = loc(1);
  node->identifierToken = loc(2);
  node->lparenToken = loc(3);
  node->rparenToken = loc(5);
  node->lbraceToken = loc(6);
  node->rbraceToken = loc(8);
  sym(1).Node = node;
} break;

case 330: {
  const auto node = new (pool) AST::FunctionExpression(stringRef(2), sym(4).FormalParameterList, sym(7).FunctionBody);
  node->functionToken = loc(1);
  if (! stringRef(2).isNull())
      node->identifierToken = loc(2);
  node->lparenToken = loc(3);
  node->rparenToken = loc(5);
  node->lbraceToken = loc(6);
  node->rbraceToken = loc(8);
  sym(1).Node = node;
} break;

case 331: {
  const auto node = new (pool) AST::FormalParameterList(stringRef(1));
  node->identifierToken = loc(1);
  sym(1).Node = node;
} break;

case 332: {
  const auto node = new (pool) AST::FormalParameterList(sym(1).FormalParameterList, stringRef(3));
  node->commaToken = loc(2);
  node->identifierToken = loc(3);
  sym(1).Node = node;
} break;

case 333: {
  sym(1).Node = nullptr;
} break;

case 334: {
  sym(1).Node = sym(1).FormalParameterList->finish ();
} break;

case 335: {
  sym(1).Node = nullptr;
} break;

case 337: {
  sym(1).Node = new (pool) AST::FunctionBody(sym(1).SourceElements->finish ());
} break;

case 339: {
  sym(1).Node = new (pool) AST::Program(sym(1).SourceElements->finish ());
} break;

case 340: {
  sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElement);
} break;

case 341: {
  sym(1).Node = new (pool) AST::SourceElements(sym(1).SourceElements, sym(2).SourceElement);
} break;

case 342: {
  sym(1).Node = new (pool) AST::StatementSourceElement(sym(1).Statement);
} break;

case 343: {
  sym(1).Node = new (pool) AST::FunctionSourceElement(sym(1).FunctionDeclaration);
} break;

case 344: {
  stringRef(1) = QStringRef();
} break;

case 346: {
  sym(1).Node = nullptr;
} break;

            } // switch
            action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT);
        } // if
    } while (action != 0);

    if (first_token == last_token) {
        const int errorState = state_stack[tos];

        // automatic insertion of `;'
        if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) {
            SavedToken &tk = token_buffer[0];
            tk.token = yytoken;
            tk.dval = yylval;
            tk.spell = yytokenspell;
            tk.loc = yylloc;

            yylloc = yyprevlloc;
            yylloc.offset += yylloc.length;
            yylloc.startColumn += yylloc.length;
            yylloc.length = 0;

            //const QString msg = qApp->translate("QmlParser", "Missing `;'");
            //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg));

            first_token = &token_buffer[0];
            last_token = &token_buffer[1];

            yytoken = T_SEMICOLON;
            yylval = 0;

            action = errorState;

            goto _Lcheck_token;
        }

        hadErrors = true;

        token_buffer[0].token = yytoken;
        token_buffer[0].dval = yylval;
        token_buffer[0].spell = yytokenspell;
        token_buffer[0].loc = yylloc;

        token_buffer[1].token = yytoken       = lexer->lex();
        token_buffer[1].dval  = yylval        = lexer->tokenValue();
        token_buffer[1].spell = yytokenspell  = lexer->tokenSpell();
        token_buffer[1].loc   = yylloc        = location(lexer);

        if (t_action(errorState, yytoken)) {
            QString msg;
            int token = token_buffer[0].token;
            if (token < 0 || token >= TERMINAL_COUNT)
                msg = qApp->translate("QmlParser", "Syntax error");
            else
                msg = qApp->translate("QmlParser", "Unexpected token `%1'").arg(QLatin1String(spell[token]));
            diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));

            action = errorState;
            goto _Lcheck_token;
        }

        static int tokens[] = {
            T_PLUS,
            T_EQ,

            T_COMMA,
            T_COLON,
            T_SEMICOLON,

            T_RPAREN, T_RBRACKET, T_RBRACE,

            T_NUMERIC_LITERAL,
            T_IDENTIFIER,

            T_LPAREN, T_LBRACKET, T_LBRACE,

            EOF_SYMBOL
        };

        for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) {
            int a = t_action(errorState, *tk);
            if (a > 0 && t_action(a, yytoken)) {
                const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[*tk]));
                diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));

                yytoken = *tk;
                yylval = 0;
                yylloc = token_buffer[0].loc;
                yylloc.length = 0;

                first_token = &token_buffer[0];
                last_token = &token_buffer[2];

                action = errorState;
                goto _Lcheck_token;
            }
        }

        for (int tk = 1; tk < TERMINAL_COUNT; ++tk) {
            if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM    ||
                tk == T_FEED_JS_STATEMENT   || tk == T_FEED_JS_EXPRESSION ||
                tk == T_FEED_JS_SOURCE_ELEMENT)
               continue;

            int a = t_action(errorState, tk);
            if (a > 0 && t_action(a, yytoken)) {
                const QString msg = qApp->translate("QmlParser", "Expected token `%1'").arg(QLatin1String(spell[tk]));
                diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));

                yytoken = tk;
                yylval = 0;
                yylloc = token_buffer[0].loc;
                yylloc.length = 0;

                action = errorState;
                goto _Lcheck_token;
            }
        }

        const QString msg = qApp->translate("QmlParser", "Syntax error");
        diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg));
    }

    return false;
}

} // namespace QbsQmlJS
