/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#include "AST.h"
#include "ASTVisitor.h"
#include "MemoryPool.h"

#include <cassert>
#include <cstddef>
#include <algorithm>

CPLUSPLUS_BEGIN_NAMESPACE

AST::AST()
{ }

AST::~AST()
{ assert(0); }

void AST::accept(ASTVisitor *visitor)
{
    if (visitor->preVisit(this))
        accept0(visitor);
    visitor->postVisit(this);
}

unsigned AttributeSpecifierAST::firstToken() const
{
    return attribute_token;
}

unsigned AttributeSpecifierAST::lastToken() const
{
    if (second_rparen_token)
        return second_rparen_token + 1;
    else if (first_rparen_token)
        return first_rparen_token + 1;
    else if (attributes)
        return attributes->lastToken();
    else if (second_lparen_token)
        return second_lparen_token + 1;
    else if (first_lparen_token)
        return first_lparen_token + 1;
    return attribute_token + 1;
}

AttributeSpecifierAST *AttributeSpecifierAST::clone(MemoryPool *pool) const
{
    AttributeSpecifierAST *ast = new (pool) AttributeSpecifierAST;
    ast->attribute_token = attribute_token;
    ast->first_lparen_token = first_lparen_token;
    ast->second_lparen_token = second_lparen_token;
    if (attributes)
        ast->attributes = attributes->clone(pool);
    ast->first_rparen_token = first_rparen_token;
    ast->second_rparen_token = second_rparen_token;
    return ast;
}

void AttributeSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (AttributeAST *attr = attributes; attr; attr = attr->next)
            accept(attr, visitor);
    }
    visitor->endVisit(this);
}

unsigned AttributeAST::firstToken() const
{
    return identifier_token;
}

unsigned AttributeAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;

    for (ExpressionListAST *it = expression_list;
            it->expression && it->next; it = it->next) {
        if (! it->next && it->expression) {
            return it->expression->lastToken();
        }
    }

    if (tag_token)
        return tag_token + 1;

    if (lparen_token)
        return lparen_token + 1;

    return identifier_token + 1;
}

AttributeAST *AttributeAST::clone(MemoryPool *pool) const
{
    AttributeAST *ast = new (pool) AttributeAST;
    ast->identifier_token = identifier_token;
    ast->lparen_token = lparen_token;
    ast->tag_token = tag_token;
    if (expression_list)
        ast->expression_list = expression_list->clone(pool);
    ast->rparen_token = rparen_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void AttributeAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (ExpressionListAST *it = expression_list; it; it = it->next)
            accept(it->expression, visitor);
    }
    visitor->endVisit(this);
}

AccessDeclarationAST *AccessDeclarationAST::clone(MemoryPool *pool) const
{
    AccessDeclarationAST *ast = new (pool) AccessDeclarationAST;
    ast->access_specifier_token = access_specifier_token;
    ast->slots_token = slots_token;
    ast->colon_token = colon_token;
    return ast;
}

void AccessDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned AccessDeclarationAST::firstToken() const
{
    return access_specifier_token;
}

unsigned AccessDeclarationAST::lastToken() const
{
    if (colon_token)
        return colon_token + 1;
    else if (slots_token)
        return slots_token + 1;
    return access_specifier_token + 1;
}

ArrayAccessAST *ArrayAccessAST::clone(MemoryPool *pool) const
{
    ArrayAccessAST *ast = new (pool) ArrayAccessAST;
    ast->lbracket_token = lbracket_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rbracket_token = rbracket_token;
    return ast;
}

void ArrayAccessAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ArrayAccessAST::firstToken() const
{
    return lbracket_token;
}

unsigned ArrayAccessAST::lastToken() const
{
    if (rbracket_token)
        return rbracket_token + 1;
    else if (expression)
        return expression->lastToken();
    return lbracket_token + 1;
}

ArrayDeclaratorAST *ArrayDeclaratorAST::clone(MemoryPool *pool) const
{
    ArrayDeclaratorAST *ast = new (pool) ArrayDeclaratorAST;
    ast->lbracket_token = lbracket_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rbracket_token = rbracket_token;
    return ast;
}

void ArrayDeclaratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(this->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ArrayDeclaratorAST::firstToken() const
{
    return lbracket_token;
}

unsigned ArrayDeclaratorAST::lastToken() const
{
    if (rbracket_token)
        return rbracket_token + 1;
    else if (expression)
        return expression->lastToken();
    return lbracket_token + 1;
}

ArrayInitializerAST *ArrayInitializerAST::clone(MemoryPool *pool) const
{
    ArrayInitializerAST *ast = new (pool) ArrayInitializerAST;
    ast->lbrace_token = lbrace_token;
    if (expression_list)
        ast->expression_list = expression_list->clone(pool);
    ast->rbrace_token = rbrace_token;
    return ast;
}

void ArrayInitializerAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (ExpressionListAST *expr = expression_list; expr; expr = expr->next)
            accept(expr->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ArrayInitializerAST::firstToken() const
{
    return lbrace_token;
}

unsigned ArrayInitializerAST::lastToken() const
{
    if (rbrace_token)
        return rbrace_token + 1;

    for (ExpressionListAST *it = expression_list; it; it = it->next) {
        if (! it->next && it->expression)
            return it->expression->lastToken();
    }

    return lbrace_token + 1;
}

AsmDefinitionAST *AsmDefinitionAST::clone(MemoryPool *pool) const
{
    AsmDefinitionAST *ast = new (pool) AsmDefinitionAST;
    ast->asm_token = asm_token;
    ast->volatile_token = volatile_token;
    ast->lparen_token = lparen_token;
    ast->rparen_token = rparen_token;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void AsmDefinitionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        // ### accept the asm operand list.
    }
    visitor->endVisit(this);
}

unsigned AsmDefinitionAST::firstToken() const
{
    return asm_token;
}

unsigned AsmDefinitionAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (rparen_token)
        return rparen_token + 1;
    else if (lparen_token)
        return lparen_token + 1;
    else if (volatile_token)
        return volatile_token + 1;
    return asm_token + 1;
}

BaseSpecifierAST *BaseSpecifierAST::clone(MemoryPool *pool) const
{
    BaseSpecifierAST *ast = new (pool) BaseSpecifierAST;
    ast->token_virtual = token_virtual;
    ast->token_access_specifier = token_access_specifier;
    if (name)
        ast->name = name->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void BaseSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned BaseSpecifierAST::firstToken() const
{
    if (token_virtual && token_access_specifier)
        return std::min(token_virtual, token_access_specifier);
    return name->firstToken();
}

unsigned BaseSpecifierAST::lastToken() const
{
    if (name)
        return name->lastToken();
    else if (token_virtual && token_access_specifier)
        return std::min(token_virtual, token_access_specifier) + 1;
    else if (token_virtual)
        return token_virtual + 1;
    else if (token_access_specifier)
        return token_access_specifier + 1;
    // assert?
    return 0;
}

unsigned QtMethodAST::firstToken() const
{ return method_token; }

unsigned QtMethodAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (declarator)
        return declarator->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    return method_token + 1;
}

QtMethodAST *QtMethodAST::clone(MemoryPool *pool) const
{
    QtMethodAST *ast = new (pool) QtMethodAST;
    ast->method_token = method_token;
    ast->lparen_token = lparen_token;
    if (declarator)
        ast->declarator = declarator->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void QtMethodAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(declarator, visitor);
    }
    visitor->endVisit(this);
}

BinaryExpressionAST *BinaryExpressionAST::clone(MemoryPool *pool) const
{
    BinaryExpressionAST *ast = new (pool) BinaryExpressionAST;
    if (left_expression)
        ast->left_expression = left_expression->clone(pool);
    ast->binary_op_token = binary_op_token;
    if (right_expression)
        ast->right_expression = right_expression->clone(pool);
    return ast;
}

void BinaryExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(left_expression, visitor);
        accept(right_expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned BinaryExpressionAST::firstToken() const
{
    return left_expression->firstToken();
}

unsigned BinaryExpressionAST::lastToken() const
{
    if (right_expression)
        return right_expression->lastToken();
    else if (binary_op_token)
        return binary_op_token + 1;
    return left_expression->lastToken();
}

BoolLiteralAST *BoolLiteralAST::clone(MemoryPool *pool) const
{
    BoolLiteralAST *ast = new (pool) BoolLiteralAST;
    ast->token = token;
    return ast;
}

void BoolLiteralAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned BoolLiteralAST::firstToken() const
{
    return token;
}

unsigned BoolLiteralAST::lastToken() const
{
    return token + 1;
}

CompoundLiteralAST *CompoundLiteralAST::clone(MemoryPool *pool) const
{
    CompoundLiteralAST *ast = new (pool) CompoundLiteralAST;
    ast->lparen_token = lparen_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    ast->rparen_token = rparen_token;
    if (initializer)
        ast->initializer = initializer->clone(pool);
    return ast;
}

void CompoundLiteralAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(type_id, visitor);
        accept(initializer, visitor);
    }
    visitor->endVisit(this);
}

unsigned CompoundLiteralAST::firstToken() const
{
    return lparen_token;
}

unsigned CompoundLiteralAST::lastToken() const
{
    if (initializer)
        return initializer->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (type_id)
        return type_id->lastToken();
    return lparen_token + 1;
}

BreakStatementAST *BreakStatementAST::clone(MemoryPool *pool) const
{
    BreakStatementAST *ast = new (pool) BreakStatementAST;
    ast->break_token = break_token;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void BreakStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned BreakStatementAST::firstToken() const
{
    return break_token;
}

unsigned BreakStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    return break_token + 1;
}

CallAST *CallAST::clone(MemoryPool *pool) const
{
    CallAST *ast = new (pool) CallAST;
    ast->lparen_token = lparen_token;
    if (expression_list)
        ast->expression_list = expression_list;
    ast->rparen_token = rparen_token;
    return ast;
}

void CallAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (ExpressionListAST *expr = expression_list;
                 expr; expr = expr->next)
            accept(expr->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned CallAST::firstToken() const
{
    return lparen_token;
}

unsigned CallAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    for (ExpressionListAST *it = expression_list; it; it = it->next) {
        if (! it->next && it->expression)
            return it->expression->lastToken();
    }
    return lparen_token + 1;
}

CaseStatementAST *CaseStatementAST::clone(MemoryPool *pool) const
{
    CaseStatementAST *ast = new (pool) CaseStatementAST;
    ast->case_token = case_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->colon_token = colon_token;
    if (statement)
        ast->statement = statement->clone(pool);
    return ast;
}

void CaseStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned CaseStatementAST::firstToken() const
{
    return case_token;
}

unsigned CaseStatementAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (colon_token)
        return colon_token + 1;
    else if (expression)
        return expression->lastToken();
    return case_token + 1;
}

CastExpressionAST *CastExpressionAST::clone(MemoryPool *pool) const
{
    CastExpressionAST *ast = new (pool) CastExpressionAST;
    ast->lparen_token = lparen_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    ast->rparen_token = rparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void CastExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned CastExpressionAST::firstToken() const
{
    return lparen_token;
}

unsigned CastExpressionAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (type_id)
        return type_id->lastToken();
    return lparen_token + 1;
}

CatchClauseAST *CatchClauseAST::clone(MemoryPool *pool) const
{
    CatchClauseAST *ast = new (pool) CatchClauseAST;
    ast->catch_token = catch_token;
    ast->lparen_token = lparen_token;
    if (exception_declaration)
        ast->exception_declaration = exception_declaration->clone(pool);
    ast->rparen_token = rparen_token;
    if (statement)
        ast->statement = statement->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void CatchClauseAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(exception_declaration, visitor);
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned CatchClauseAST::firstToken() const
{
    return catch_token;
}

unsigned CatchClauseAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    for (DeclarationAST *it = exception_declaration; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    if (lparen_token)
        return lparen_token + 1;

    return catch_token + 1;
}

ClassSpecifierAST *ClassSpecifierAST::clone(MemoryPool *pool) const
{
    ClassSpecifierAST *ast = new (pool) ClassSpecifierAST;
    ast->classkey_token = classkey_token;
    if (attributes)
        ast->attributes = attributes->clone(pool);
    if (name)
        ast->name = name->clone(pool);
    ast->colon_token = colon_token;
    if (base_clause)
        ast->base_clause = base_clause->clone(pool);
    ast->lbrace_token = lbrace_token;
    if (member_specifiers)
        ast->member_specifiers = member_specifiers->clone(pool);
    ast->rbrace_token = rbrace_token;
    return ast;
}

void ClassSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = attributes; spec; spec = spec->next)
            accept(spec, visitor);
        accept(name, visitor);
        for (BaseSpecifierAST *spec = base_clause; spec; spec = spec->next)
            accept(spec, visitor);
        for (DeclarationAST *decl = member_specifiers; decl; decl = decl->next)
            accept(decl, visitor);
    }
    visitor->endVisit(this);
}

unsigned ClassSpecifierAST::firstToken() const
{
    return classkey_token;
}

unsigned ClassSpecifierAST::lastToken() const
{
    if (rbrace_token)
        return rbrace_token + 1;

    for (DeclarationAST *it = member_specifiers; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (lbrace_token)
        return lbrace_token + 1;

    for (BaseSpecifierAST *it = base_clause; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (colon_token)
        return colon_token + 1;

    if (name)
        return name->lastToken();

    for (SpecifierAST *it = attributes; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return classkey_token + 1;
}

CompoundStatementAST *CompoundStatementAST::clone(MemoryPool *pool) const
{
    CompoundStatementAST *ast = new (pool) CompoundStatementAST;
    ast->lbrace_token = lbrace_token;
    if (statements)
        ast->statements = statements->clone(pool);
    ast->rbrace_token = rbrace_token;
    return ast;
}

void CompoundStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (StatementAST *stmt = statements; stmt; stmt = stmt->next)
            accept(stmt, visitor);
    }
    visitor->endVisit(this);
}

unsigned CompoundStatementAST::firstToken() const
{
    return lbrace_token;
}

unsigned CompoundStatementAST::lastToken() const
{
    if (rbrace_token)
        return rbrace_token + 1;

    for (StatementAST *it = statements; it ; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return lbrace_token + 1;
}

ConditionAST *ConditionAST::clone(MemoryPool *pool) const
{
    ConditionAST *ast = new (pool) ConditionAST;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (declarator)
        ast->declarator = declarator->clone(pool);
    return ast;
}

void ConditionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        accept(declarator, visitor);
    }
    visitor->endVisit(this);
}

unsigned ConditionAST::firstToken() const
{
    if (type_specifier)
        return type_specifier->firstToken();

    return declarator->firstToken();
}

unsigned ConditionAST::lastToken() const
{
    if (declarator)
        return declarator->lastToken();

    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    // ### assert?
    return 0;
}

ConditionalExpressionAST *ConditionalExpressionAST::clone(MemoryPool *pool) const
{
    ConditionalExpressionAST *ast = new (pool) ConditionalExpressionAST;
    if (condition)
        ast->condition = condition->clone(pool);
    ast->question_token = question_token;
    if (left_expression)
        ast->left_expression = left_expression->clone(pool);
    ast->colon_token = colon_token;
    if (right_expression)
        ast->right_expression = right_expression->clone(pool);
    return ast;
}

void ConditionalExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(condition, visitor);
        accept(left_expression, visitor);
        accept(right_expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ConditionalExpressionAST::firstToken() const
{
    return condition->firstToken();
}

unsigned ConditionalExpressionAST::lastToken() const
{
    if (right_expression)
        return right_expression->lastToken();
    else if (colon_token)
        return colon_token + 1;
    else if (left_expression)
        return left_expression->lastToken();
    else if (question_token)
        return question_token + 1;
    else if (condition)
        return condition->lastToken();
    // ### assert?
    return 0;
}

ContinueStatementAST *ContinueStatementAST::clone(MemoryPool *pool) const
{
    ContinueStatementAST *ast = new (pool) ContinueStatementAST;
    ast->continue_token = continue_token;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void ContinueStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned ContinueStatementAST::firstToken() const
{
    return continue_token;
}

unsigned ContinueStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    return continue_token + 1;
}

ConversionFunctionIdAST *ConversionFunctionIdAST::clone(MemoryPool *pool) const
{
    ConversionFunctionIdAST *ast = new (pool) ConversionFunctionIdAST;
    ast->operator_token = operator_token;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (ptr_operators)
        ast->ptr_operators = ptr_operators->clone(pool);
    return ast;
}

void ConversionFunctionIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op;
                 ptr_op = static_cast<PtrOperatorAST *>(ptr_op->next))
            accept(ptr_op, visitor);
    }
    visitor->endVisit(this);
}

unsigned ConversionFunctionIdAST::firstToken() const
{
    return operator_token;
}

unsigned ConversionFunctionIdAST::lastToken() const
{
    for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return operator_token + 1;
}

CppCastExpressionAST *CppCastExpressionAST::clone(MemoryPool *pool) const
{
    CppCastExpressionAST *ast = new (pool) CppCastExpressionAST;
    ast->cast_token = cast_token;
    ast->less_token = less_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    ast->greater_token = greater_token;
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void CppCastExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(type_id, visitor);
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned CppCastExpressionAST::firstToken() const
{
    return cast_token;
}

unsigned CppCastExpressionAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    else if (greater_token)
        return greater_token + 1;
    else if (type_id)
        return type_id->lastToken();
    else if (less_token)
        return less_token + 1;
    return cast_token + 1;
}

CtorInitializerAST *CtorInitializerAST::clone(MemoryPool *pool) const
{
    CtorInitializerAST *ast = new (pool) CtorInitializerAST;
    ast->colon_token = colon_token;
    if (member_initializers)
        ast->member_initializers = member_initializers->clone(pool);
    return ast;
}

void CtorInitializerAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (MemInitializerAST *mem_init = member_initializers;
                 mem_init; mem_init = mem_init->next)
            accept(mem_init, visitor);
    }
    visitor->endVisit(this);
}

unsigned CtorInitializerAST::firstToken() const
{
    return colon_token;
}

unsigned CtorInitializerAST::lastToken() const
{
    for (MemInitializerAST *it = member_initializers; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    return colon_token + 1;
}

DeclaratorAST *DeclaratorAST::clone(MemoryPool *pool) const
{
    DeclaratorAST *ast = new (pool) DeclaratorAST;
    if (ptr_operators)
        ast->ptr_operators = ptr_operators->clone(pool);
    if (core_declarator)
        ast->core_declarator = core_declarator->clone(pool);
    if (postfix_declarators)
        ast->postfix_declarators = postfix_declarators->clone(pool);
    if (attributes)
        ast->attributes = attributes->clone(pool);
    if (initializer)
        ast->initializer = initializer->clone(pool);
    return ast;
}

void DeclaratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; ptr_op = ptr_op->next) {
            accept(ptr_op, visitor);
        }
        accept(core_declarator, visitor);
        for (PostfixDeclaratorAST *fx = postfix_declarators; fx; fx = fx->next) {
            accept(fx, visitor);
        }
        accept(attributes, visitor);
        accept(initializer, visitor);
    }
    visitor->endVisit(this);
}

unsigned DeclaratorAST::firstToken() const
{
    if (ptr_operators)
        return ptr_operators->firstToken();
    else if (core_declarator)
        return core_declarator->firstToken();
    else if (postfix_declarators)
        return postfix_declarators->firstToken();
    else if (attributes)
        return attributes->firstToken();
    else if (initializer)
        return initializer->firstToken();
    // ### assert?
    return 0;
}

unsigned DeclaratorAST::lastToken() const
{
    if (initializer)
        return initializer->lastToken();

    for (SpecifierAST *it = attributes; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    for (PostfixDeclaratorAST *it = postfix_declarators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (core_declarator)
        return core_declarator->lastToken();

    for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    // ### assert?
    return 0;
}

DeclarationStatementAST *DeclarationStatementAST::clone(MemoryPool *pool) const
{
    DeclarationStatementAST *ast = new (pool) DeclarationStatementAST;
    if (declaration)
        ast->declaration = declaration->clone(pool);
    return ast;
}

void DeclarationStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(declaration, visitor);
    }
    visitor->endVisit(this);
}

unsigned DeclarationStatementAST::firstToken() const
{
    return declaration->firstToken();
}

unsigned DeclarationStatementAST::lastToken() const
{
    return declaration->lastToken();
}

DeclaratorIdAST *DeclaratorIdAST::clone(MemoryPool *pool) const
{
    DeclaratorIdAST *ast = new (pool) DeclaratorIdAST;
    if (name)
        ast->name = name->clone(pool);
    return ast;
}

void DeclaratorIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned DeclaratorIdAST::firstToken() const
{
    return name->firstToken();
}

unsigned DeclaratorIdAST::lastToken() const
{
    return name->lastToken();
}

DeclaratorListAST *DeclaratorListAST::clone(MemoryPool *pool) const
{
    DeclaratorListAST *ast = new (pool) DeclaratorListAST;
    if (declarator)
        ast->declarator = declarator->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void DeclaratorListAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (DeclaratorListAST *it = this; it; it = it->next)
            accept(it->declarator, visitor);
    }
    visitor->endVisit(this);
}

unsigned DeclaratorListAST::firstToken() const
{
    return declarator->firstToken();
}

unsigned DeclaratorListAST::lastToken() const
{
    for (const DeclaratorListAST *it = this; it; it = it->next) {
        if (! it->next)
            return it->declarator->lastToken();
    }
    return 0;
}

DeleteExpressionAST *DeleteExpressionAST::clone(MemoryPool *pool) const
{
    DeleteExpressionAST *ast = new (pool) DeleteExpressionAST;
    ast->scope_token = scope_token;
    ast->delete_token = delete_token;
    ast->lbracket_token = lbracket_token;
    ast->rbracket_token = rbracket_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void DeleteExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned DeleteExpressionAST::firstToken() const
{
    if (scope_token)
        return scope_token;
    return delete_token;
}

unsigned DeleteExpressionAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    else if (rbracket_token)
        return rbracket_token + 1;
    else if (lbracket_token)
        return lbracket_token + 1;
    else if (delete_token)
        return delete_token + 1;
    return scope_token + 1;
}

DestructorNameAST *DestructorNameAST::clone(MemoryPool *pool) const
{
    DestructorNameAST *ast = new (pool) DestructorNameAST;
    ast->tilde_token = tilde_token;
    ast->identifier_token = identifier_token;
    return ast;
}

void DestructorNameAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned DestructorNameAST::firstToken() const
{
    return tilde_token;
}

unsigned DestructorNameAST::lastToken() const
{
    if (identifier_token)
        return identifier_token + 1;
    return tilde_token + 1;
}

DoStatementAST *DoStatementAST::clone(MemoryPool *pool) const
{
    DoStatementAST *ast = new (pool) DoStatementAST;
    ast->do_token = do_token;
    if (statement)
        ast->statement = statement->clone(pool);
    ast->while_token = while_token;
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void DoStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(statement, visitor);
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned DoStatementAST::firstToken() const
{
    return do_token;
}

unsigned DoStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    else if (while_token)
        return while_token + 1;
    else if (statement)
        return statement->lastToken();
    return do_token + 1;
}

ElaboratedTypeSpecifierAST *ElaboratedTypeSpecifierAST::clone(MemoryPool *pool) const
{
    ElaboratedTypeSpecifierAST *ast = new (pool) ElaboratedTypeSpecifierAST;
    ast->classkey_token = classkey_token;
    if (name)
        ast->name = name->clone(pool);
    return ast;
}

void ElaboratedTypeSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned ElaboratedTypeSpecifierAST::firstToken() const
{
    return classkey_token;
}

unsigned ElaboratedTypeSpecifierAST::lastToken() const
{
    if (name)
        return name->lastToken();
    return classkey_token + 1;
}

EmptyDeclarationAST *EmptyDeclarationAST::clone(MemoryPool *pool) const
{
    EmptyDeclarationAST *ast = new (pool) EmptyDeclarationAST;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void EmptyDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned EmptyDeclarationAST::firstToken() const
{
    return semicolon_token;
}

unsigned EmptyDeclarationAST::lastToken() const
{
    return semicolon_token + 1;
}

EnumSpecifierAST *EnumSpecifierAST::clone(MemoryPool *pool) const
{
    EnumSpecifierAST *ast = new (pool) EnumSpecifierAST;
    ast->enum_token = enum_token;
    if (name)
        ast->name = name->clone(pool);
    ast->lbrace_token = lbrace_token;
    if (enumerators)
        ast->enumerators = enumerators->clone(pool);
    ast->rbrace_token = rbrace_token;
    return ast;
}

void EnumSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
        for (EnumeratorAST *enumerator = enumerators; enumerator;
                 enumerator = enumerator->next)
            accept(enumerator, visitor);
    }
    visitor->endVisit(this);
}

unsigned EnumSpecifierAST::firstToken() const
{
    return enum_token;
}

unsigned EnumSpecifierAST::lastToken() const
{
    if (rbrace_token)
        return rbrace_token + 1;

    for (EnumeratorAST *it = enumerators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (lbrace_token)
        return lbrace_token + 1;
    if (name)
        return name->lastToken();

    return enum_token + 1;
}

EnumeratorAST *EnumeratorAST::clone(MemoryPool *pool) const
{
    EnumeratorAST *ast = new (pool) EnumeratorAST;
    ast->identifier_token = identifier_token;
    ast->equal_token = equal_token;
    if (expression)
        ast->expression = expression->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void EnumeratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned EnumeratorAST::firstToken() const
{
    return identifier_token;
}

unsigned EnumeratorAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    else if (equal_token)
        return equal_token + 1;
    return identifier_token + 1;
}

ExceptionDeclarationAST *ExceptionDeclarationAST::clone(MemoryPool *pool) const
{
    ExceptionDeclarationAST *ast = new (pool) ExceptionDeclarationAST;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (declarator)
        ast->declarator = declarator->clone(pool);
    ast->dot_dot_dot_token = dot_dot_dot_token;
    return ast;
}

void ExceptionDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        accept(declarator, visitor);
    }
    visitor->endVisit(this);
}

unsigned ExceptionDeclarationAST::firstToken() const
{
    if (type_specifier)
        return type_specifier->firstToken();
    if (declarator)
        return declarator->firstToken();
    return dot_dot_dot_token;
}

unsigned ExceptionDeclarationAST::lastToken() const
{
    if (dot_dot_dot_token)
        return dot_dot_dot_token + 1;
    else if (declarator)
        return declarator->lastToken();
    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    return 0;
}

ExceptionSpecificationAST *ExceptionSpecificationAST::clone(MemoryPool *pool) const
{
    ExceptionSpecificationAST *ast = new (pool) ExceptionSpecificationAST;
    ast->throw_token = throw_token;
    ast->lparen_token = lparen_token;
    ast->dot_dot_dot_token = dot_dot_dot_token;
    if (type_ids)
        ast->type_ids = type_ids->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void ExceptionSpecificationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (ExpressionListAST *type_id = type_ids; type_id;
                 type_id = type_id->next)
            accept(type_id->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ExceptionSpecificationAST::firstToken() const
{
    return throw_token;
}

unsigned ExceptionSpecificationAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;

    for (ExpressionListAST *it = type_ids; it; it = it->next) {
        if (! it->next && it->expression)
            return it->expression->lastToken();
    }

    if (dot_dot_dot_token)
        return dot_dot_dot_token + 1;
    else if (lparen_token)
        return lparen_token + 1;

    return throw_token + 1;
}

ExpressionListAST *ExpressionListAST::clone(MemoryPool *pool) const
{
    ExpressionListAST *ast = new (pool) ExpressionListAST;
    if (expression)
        ast->expression = expression->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void ExpressionListAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (const ExpressionListAST *it = this; it; it = it->next) {
            accept(it->expression, visitor);
        }
    }
    visitor->endVisit(this);
}

unsigned ExpressionListAST::firstToken() const
{
    return expression->firstToken();
}

unsigned ExpressionListAST::lastToken() const
{
    for (const ExpressionListAST *it = this; it; it = it->next) {
        if (! it->next)
            return it->expression->lastToken();
    }
    return 0;
}

ExpressionOrDeclarationStatementAST *ExpressionOrDeclarationStatementAST::clone(MemoryPool *pool) const
{
    ExpressionOrDeclarationStatementAST *ast = new (pool) ExpressionOrDeclarationStatementAST;
    if (expression)
        ast->expression = expression->clone(pool);
    if (declaration)
        ast->declaration = declaration->clone(pool);
    return ast;
}

void ExpressionOrDeclarationStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(declaration, visitor);
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ExpressionOrDeclarationStatementAST::firstToken() const
{
    return declaration->firstToken();
}

unsigned ExpressionOrDeclarationStatementAST::lastToken() const
{
    return declaration->lastToken();
}

ExpressionStatementAST *ExpressionStatementAST::clone(MemoryPool *pool) const
{
    ExpressionStatementAST *ast = new (pool) ExpressionStatementAST;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void ExpressionStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ExpressionStatementAST::firstToken() const
{
    if (expression)
        return expression->firstToken();
    return semicolon_token;
}

unsigned ExpressionStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (expression)
        return expression->lastToken();
    // ### assert?
    return 0;
}

ForStatementAST *ForStatementAST::clone(MemoryPool *pool) const
{
    ForStatementAST *ast = new (pool) ForStatementAST;
    ast->for_token = for_token;
    ast->lparen_token = lparen_token;
    if (initializer)
        ast->initializer = initializer->clone(pool);
    if (condition)
        ast->condition = condition->clone(pool);
    ast->semicolon_token = semicolon_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    if (statement)
        ast->statement = statement->clone(pool);
    return ast;
}

void ForStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(initializer, visitor);
        accept(condition, visitor);
        accept(expression, visitor);
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned ForStatementAST::firstToken() const
{
    return for_token;
}

unsigned ForStatementAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    else if (semicolon_token)
        return semicolon_token + 1;
    else if (condition)
        return condition->lastToken();
    else if (initializer)
        return initializer->lastToken();
    else if (lparen_token)
        return lparen_token + 1;

    return for_token + 1;
}

FunctionDeclaratorAST *FunctionDeclaratorAST::clone(MemoryPool *pool) const
{
    FunctionDeclaratorAST *ast = new (pool) FunctionDeclaratorAST;
    ast->lparen_token = lparen_token;
    if (parameters)
        ast->parameters = parameters->clone(pool);
    ast->rparen_token = rparen_token;
    if (cv_qualifier_seq)
        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
    if (exception_specification)
        ast->exception_specification = exception_specification->clone(pool);
    return ast;
}

void FunctionDeclaratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(parameters, visitor);
        for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next)
            accept(it, visitor);
        accept(exception_specification, visitor);
    }
    visitor->endVisit(this);
}

unsigned FunctionDeclaratorAST::firstToken() const
{
    return lparen_token;
}

unsigned FunctionDeclaratorAST::lastToken() const
{
    if (exception_specification)
        return exception_specification->lastToken();

    for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (rparen_token)
        return rparen_token + 1;
    else if (parameters)
        return parameters->lastToken();

    return lparen_token + 1;
}

FunctionDefinitionAST *FunctionDefinitionAST::clone(MemoryPool *pool) const
{
    FunctionDefinitionAST *ast = new (pool) FunctionDefinitionAST;
    if (decl_specifier_seq)
        ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
    if (declarator)
        ast->declarator = declarator->clone(pool);
    if (ctor_initializer)
        ast->ctor_initializer = ctor_initializer->clone(pool);
    if (function_body)
        ast->function_body = function_body->clone(pool);
    return ast;
}

void FunctionDefinitionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = decl_specifier_seq; spec;
                 spec = spec->next)
            accept(spec, visitor);
        accept(declarator, visitor);
        accept(ctor_initializer, visitor);
        accept(function_body, visitor);
    }
    visitor->endVisit(this);
}

unsigned FunctionDefinitionAST::firstToken() const
{
    if (decl_specifier_seq)
        return decl_specifier_seq->firstToken();
    else if (declarator)
        return declarator->firstToken();
    else if (ctor_initializer)
        return ctor_initializer->firstToken();
    return function_body->firstToken();
}

unsigned FunctionDefinitionAST::lastToken() const
{
    if (function_body)
        return function_body->lastToken();
    else if (ctor_initializer)
        return ctor_initializer->lastToken();
    if (declarator)
        return declarator->lastToken();

    for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    // ### assert
    return 0;
}

GotoStatementAST *GotoStatementAST::clone(MemoryPool *pool) const
{
    GotoStatementAST *ast = new (pool) GotoStatementAST;
    ast->goto_token = goto_token;
    ast->identifier_token = identifier_token;
    ast->semicolon_token = semicolon_token;
    return ast;
}

void GotoStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned GotoStatementAST::firstToken() const
{
    return goto_token;
}

unsigned GotoStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (identifier_token)
        return identifier_token + 1;
    else if (goto_token)
        return goto_token + 1;
    return 0;
}

IfStatementAST *IfStatementAST::clone(MemoryPool *pool) const
{
    IfStatementAST *ast = new (pool) IfStatementAST;
    ast->if_token = if_token;
    ast->lparen_token = lparen_token;
    if (condition)
        ast->condition = condition->clone(pool);
    ast->rparen_token = rparen_token;
    if (statement)
        ast->statement = statement->clone(pool);
    ast->else_token = else_token;
    if (else_statement)
        ast->else_statement = else_statement->clone(pool);
    return ast;
}

void IfStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(condition, visitor);
        accept(statement, visitor);
        accept(else_statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned IfStatementAST::firstToken() const
{
    return if_token;
}

unsigned IfStatementAST::lastToken() const
{
    if (else_statement)
        return else_statement->lastToken();
    else if (else_token)
        return else_token + 1;
    else if (statement)
        return statement->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (condition)
        return condition->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    return if_token + 1;
}

LabeledStatementAST *LabeledStatementAST::clone(MemoryPool *pool) const
{
    LabeledStatementAST *ast = new (pool) LabeledStatementAST;
    ast->label_token = label_token;
    ast->colon_token = colon_token;
    if (statement)
        ast->statement = statement->clone(pool);
    return ast;
}

void LabeledStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned LabeledStatementAST::firstToken() const
{
    return label_token;
}

unsigned LabeledStatementAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (colon_token)
        return colon_token + 1;
    return label_token + 1;
}

LinkageBodyAST *LinkageBodyAST::clone(MemoryPool *pool) const
{
    LinkageBodyAST *ast = new (pool) LinkageBodyAST;
    ast->lbrace_token = lbrace_token;
    if (declarations)
        ast->declarations = declarations->clone(pool);
    ast->rbrace_token = rbrace_token;
    return ast;
}

void LinkageBodyAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (DeclarationAST *decl = declarations; decl;
                 decl = decl->next)
            accept(decl, visitor);
    }
    visitor->endVisit(this);
}

unsigned LinkageBodyAST::firstToken() const
{
    return lbrace_token;
}

unsigned LinkageBodyAST::lastToken() const
{
    if (rbrace_token)
        return rbrace_token + 1;

    for (DeclarationAST *it = declarations; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return lbrace_token + 1;
}

LinkageSpecificationAST *LinkageSpecificationAST::clone(MemoryPool *pool) const
{
    LinkageSpecificationAST *ast = new (pool) LinkageSpecificationAST;
    ast->extern_token = extern_token;
    ast->extern_type = extern_type;
    if (declaration)
        ast->declaration = declaration->clone(pool);
    return ast;
}

void LinkageSpecificationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(declaration, visitor);
    }
    visitor->endVisit(this);
}

unsigned LinkageSpecificationAST::firstToken() const
{
    return extern_token;
}

unsigned LinkageSpecificationAST::lastToken() const
{
    if (declaration)
        return declaration->lastToken();
    else if (extern_type)
        return extern_type + 1;
    return extern_token + 1;
}

MemInitializerAST *MemInitializerAST::clone(MemoryPool *pool) const
{
    MemInitializerAST *ast = new (pool) MemInitializerAST;
    if (name)
        ast->name = name->clone(pool);
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void MemInitializerAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned MemInitializerAST::firstToken() const
{
    return name->firstToken();
}

unsigned MemInitializerAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    return name->lastToken();
}

MemberAccessAST *MemberAccessAST::clone(MemoryPool *pool) const
{
    MemberAccessAST *ast = new (pool) MemberAccessAST;
    ast->access_token = access_token;
    ast->template_token = template_token;
    if (member_name)
        ast->member_name = member_name->clone(pool);
    return ast;
}

void MemberAccessAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(member_name, visitor);
    }
    visitor->endVisit(this);
}

unsigned MemberAccessAST::firstToken() const
{
    return access_token;
}

unsigned MemberAccessAST::lastToken() const
{
    if (member_name)
        return member_name->lastToken();
    else if (template_token)
        return template_token + 1;
    return access_token + 1;
}

NamedTypeSpecifierAST *NamedTypeSpecifierAST::clone(MemoryPool *pool) const
{
    NamedTypeSpecifierAST *ast = new (pool) NamedTypeSpecifierAST;
    if (name)
        ast->name = name->clone(pool);
    return ast;
}

void NamedTypeSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned NamedTypeSpecifierAST::firstToken() const
{
    return name->firstToken();
}

unsigned NamedTypeSpecifierAST::lastToken() const
{
    return name->lastToken();
}

NamespaceAST *NamespaceAST::clone(MemoryPool *pool) const
{
    NamespaceAST *ast = new (pool) NamespaceAST;
    ast->namespace_token = namespace_token;
    ast->identifier_token = identifier_token;
    if (attributes)
        ast->attributes = attributes->clone(pool);
    if (linkage_body)
        ast->linkage_body = linkage_body->clone(pool);
    return ast;
}

void NamespaceAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *attr = attributes; attr; attr = attr->next) {
            accept(attr, visitor);
        }
        accept(linkage_body, visitor);
    }
    visitor->endVisit(this);
}

unsigned NamespaceAST::firstToken() const
{
    return namespace_token;
}

unsigned NamespaceAST::lastToken() const
{
    if (linkage_body)
        return linkage_body->lastToken();

    for (SpecifierAST *it = attributes; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (identifier_token)
        return identifier_token + 1;

    return namespace_token + 1;
}

NamespaceAliasDefinitionAST *NamespaceAliasDefinitionAST::clone(MemoryPool *pool) const
{
    NamespaceAliasDefinitionAST *ast = new (pool) NamespaceAliasDefinitionAST;
    ast->namespace_token = namespace_token;
    ast->namespace_name = namespace_name;
    ast->equal_token = equal_token;
    if (name)
        ast->name = name->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void NamespaceAliasDefinitionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned NamespaceAliasDefinitionAST::firstToken() const
{
    return namespace_token;
}

unsigned NamespaceAliasDefinitionAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (name)
        return name->lastToken();
    else if (equal_token)
        return equal_token + 1;
    else if (namespace_name)
        return namespace_name + 1;
    return namespace_token + 1;
}

NestedDeclaratorAST *NestedDeclaratorAST::clone(MemoryPool *pool) const
{
    NestedDeclaratorAST *ast = new (pool) NestedDeclaratorAST;
    ast->lparen_token = lparen_token;
    if (declarator)
        ast->declarator = declarator->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void NestedDeclaratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(declarator, visitor);
    }
    visitor->endVisit(this);
}

unsigned NestedDeclaratorAST::firstToken() const
{
    return lparen_token;
}

unsigned NestedDeclaratorAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (declarator)
        return declarator->lastToken();
    return lparen_token + 1;
}

NestedExpressionAST *NestedExpressionAST::clone(MemoryPool *pool) const
{
    NestedExpressionAST *ast = new (pool) NestedExpressionAST;
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void NestedExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned NestedExpressionAST::firstToken() const
{
    return lparen_token;
}

unsigned NestedExpressionAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    return lparen_token + 1;
}

NestedNameSpecifierAST *NestedNameSpecifierAST::clone(MemoryPool *pool) const
{
    NestedNameSpecifierAST *ast = new (pool) NestedNameSpecifierAST;
    if (class_or_namespace_name)
        ast->class_or_namespace_name = class_or_namespace_name->clone(pool);
    ast->scope_token = scope_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void NestedNameSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(class_or_namespace_name, visitor);
        accept(next, visitor); // ### I'm not 100% sure about this.
    }
    visitor->endVisit(this);
}

unsigned NestedNameSpecifierAST::firstToken() const
{
    return class_or_namespace_name->firstToken();
}

unsigned NestedNameSpecifierAST::lastToken() const
{
    if (scope_token)
        return scope_token + 1;
    return class_or_namespace_name->lastToken();
}

NewPlacementAST *NewPlacementAST::clone(MemoryPool *pool) const
{
    NewPlacementAST *ast = new (pool) NewPlacementAST;
    ast->lparen_token = lparen_token;
    if (expression_list)
        ast->expression_list = expression_list->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void NewPlacementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (ExpressionListAST *it = expression_list; it; it = it->next) {
            accept(it->expression, visitor);
        }
    }
    visitor->endVisit(this);
}

unsigned NewPlacementAST::firstToken() const
{
    return lparen_token;
}

unsigned NewPlacementAST::lastToken() const
{
    return rparen_token + 1;
}

NewArrayDeclaratorAST *NewArrayDeclaratorAST::clone(MemoryPool *pool) const
{
    NewArrayDeclaratorAST *ast = new (pool) NewArrayDeclaratorAST;
    ast->lbracket_token = lbracket_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rbracket_token = rbracket_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void NewArrayDeclaratorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
        accept(next, visitor);
    }
    visitor->endVisit(this);
}

unsigned NewArrayDeclaratorAST::firstToken() const
{
    return lbracket_token;
}

unsigned NewArrayDeclaratorAST::lastToken() const
{
    return rbracket_token + 1;
}

NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const
{
    NewExpressionAST *ast = new (pool) NewExpressionAST;

    ast->scope_token = scope_token;
    ast->new_token = new_token;
    if (new_placement)
        ast->new_placement = new_placement->clone(pool);
    ast->lparen_token = lparen_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    ast->rparen_token = rparen_token;
    if (new_type_id)
        ast->new_type_id = new_type_id->clone(pool);
    if (new_initializer)
        ast->new_initializer = new_initializer->clone(pool);
    return ast;
}

void NewExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(new_placement, visitor);
        accept(type_id, visitor);
        accept(new_type_id, visitor);
        accept(new_initializer, visitor);
    }
    visitor->endVisit(this);
}

unsigned NewExpressionAST::firstToken() const
{
    if (scope_token)
        return scope_token;
    return new_token;
}

unsigned NewExpressionAST::lastToken() const
{
    // ### FIXME
    if (new_token)
        return new_token + 1;
    else if (scope_token)
        return scope_token + 1;
    // ### assert?
    return 0;
}

NewInitializerAST *NewInitializerAST::clone(MemoryPool *pool) const
{
    NewInitializerAST *ast = new (pool) NewInitializerAST;
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void NewInitializerAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned NewInitializerAST::firstToken() const
{
    return lparen_token;
}

unsigned NewInitializerAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    return lparen_token + 1;
}

TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const
{
    TypeIdAST *ast = new (pool) TypeIdAST;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (declarator)
        ast->declarator = declarator->clone(pool);
    return ast;
}

NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const
{
    NewTypeIdAST *ast = new (pool) NewTypeIdAST;

    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (ptr_operators)
        ast->ptr_operators = ptr_operators->clone(pool);
    if (new_array_declarators)
        ast->new_array_declarators = new_array_declarators->clone(pool);
    return ast;
}

void NewTypeIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);

        for (PtrOperatorAST *it = ptr_operators; it; it = it->next)
            accept(it, visitor);

        for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next)
            accept(it, visitor);

    }
    visitor->endVisit(this);
}

unsigned NewTypeIdAST::firstToken() const
{
    return type_specifier->firstToken();
}

unsigned NewTypeIdAST::lastToken() const
{
    for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    for (PtrOperatorAST *it = ptr_operators; it; it = it->next) {
        if (it->next)
            return it->lastToken();
    }

    if (type_specifier)
        return type_specifier->lastToken();

    // ### assert?
    return 0;
}

NumericLiteralAST *NumericLiteralAST::clone(MemoryPool *pool) const
{
    NumericLiteralAST *ast = new (pool) NumericLiteralAST;
    ast->token = token;
    return ast;
}

void NumericLiteralAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned NumericLiteralAST::firstToken() const
{
    return token;
}

unsigned NumericLiteralAST::lastToken() const
{
    return token + 1;
}

OperatorAST *OperatorAST::clone(MemoryPool *pool) const
{
    OperatorAST *ast = new (pool) OperatorAST;
    ast->op_token = op_token;
    ast->open_token = open_token;
    ast->close_token = close_token;
    return ast;
}

void OperatorAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned OperatorAST::firstToken() const
{
    return op_token;
}

unsigned OperatorAST::lastToken() const
{
    if (close_token)
        return close_token + 1;
    else if (open_token)
        return open_token + 1;
    return op_token + 1;
}

OperatorFunctionIdAST *OperatorFunctionIdAST::clone(MemoryPool *pool) const
{
    OperatorFunctionIdAST *ast = new (pool) OperatorFunctionIdAST;
    ast->operator_token = operator_token;
    if (op)
        ast->op = op->clone(pool);
    return ast;
}

void OperatorFunctionIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(op, visitor);
    }
    visitor->endVisit(this);
}

unsigned OperatorFunctionIdAST::firstToken() const
{
    return operator_token;
}

unsigned OperatorFunctionIdAST::lastToken() const
{
    if (op)
        return op->lastToken();
    return operator_token + 1;
}

ParameterDeclarationAST *ParameterDeclarationAST::clone(MemoryPool *pool) const
{
    ParameterDeclarationAST *ast = new (pool) ParameterDeclarationAST;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    if (declarator)
        ast->declarator = declarator->clone(pool);
    ast->equal_token = equal_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void ParameterDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        accept(declarator, visitor);
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ParameterDeclarationAST::firstToken() const
{
    return type_specifier->firstToken();
}

unsigned ParameterDeclarationAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    else if (equal_token)
        return equal_token + 1;
    else if (declarator)
        return declarator->lastToken();
    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    // ### assert?
    return 0;
}

ParameterDeclarationClauseAST *ParameterDeclarationClauseAST::clone(MemoryPool *pool) const
{
    ParameterDeclarationClauseAST *ast = new (pool) ParameterDeclarationClauseAST;
    if (parameter_declarations)
        ast->parameter_declarations = parameter_declarations;
    ast->dot_dot_dot_token = dot_dot_dot_token;
    return ast;
}

void ParameterDeclarationClauseAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (DeclarationAST *param = parameter_declarations; param;
                param = param->next)
            accept(param, visitor);
    }
    visitor->endVisit(this);
}

unsigned ParameterDeclarationClauseAST::firstToken() const
{
    if (parameter_declarations)
        return parameter_declarations->firstToken();
    return dot_dot_dot_token;
}

unsigned ParameterDeclarationClauseAST::lastToken() const
{
    if (dot_dot_dot_token)
        return dot_dot_dot_token + 1;
    return parameter_declarations->lastToken();
}

PointerAST *PointerAST::clone(MemoryPool *pool) const
{
    PointerAST *ast = new (pool) PointerAST;
    ast->star_token = star_token;
    if (cv_qualifier_seq)
        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
    return ast;
}

void PointerAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = cv_qualifier_seq; spec;
                 spec = spec->next)
            accept(spec, visitor);
    }
    visitor->endVisit(this);
}

unsigned PointerAST::firstToken() const
{
    return star_token;
}

unsigned PointerAST::lastToken() const
{
    for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    return star_token + 1;
}

PointerToMemberAST *PointerToMemberAST::clone(MemoryPool *pool) const
{
    PointerToMemberAST *ast = new (pool) PointerToMemberAST;
    ast->global_scope_token = global_scope_token;
    if (nested_name_specifier)
        ast->nested_name_specifier = nested_name_specifier->clone(pool);
    ast->star_token = star_token;
    if (cv_qualifier_seq)
        ast->cv_qualifier_seq = cv_qualifier_seq->clone(pool);
    return ast;
}

void PointerToMemberAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(nested_name_specifier, visitor);
        for (SpecifierAST *spec = cv_qualifier_seq; spec;
                 spec = spec->next)
            accept(spec, visitor);
    }
    visitor->endVisit(this);
}

unsigned PointerToMemberAST::firstToken() const
{
    if (global_scope_token)
        return global_scope_token;
    else if (nested_name_specifier)
        return nested_name_specifier->firstToken();
    return star_token;
}

unsigned PointerToMemberAST::lastToken() const
{
    for (SpecifierAST *it = cv_qualifier_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (star_token)
        return star_token + 1;

    for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (global_scope_token)
        return global_scope_token + 1;

    return 0;
}

PostIncrDecrAST *PostIncrDecrAST::clone(MemoryPool *pool) const
{
    PostIncrDecrAST *ast = new (pool) PostIncrDecrAST;
    ast->incr_decr_token = incr_decr_token;
    return ast;
}

void PostIncrDecrAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned PostIncrDecrAST::firstToken() const
{
    return incr_decr_token;
}

unsigned PostIncrDecrAST::lastToken() const
{
    return incr_decr_token + 1;
}

PostfixExpressionAST *PostfixExpressionAST::clone(MemoryPool *pool) const
{
    PostfixExpressionAST *ast = new (pool) PostfixExpressionAST;
    if (base_expression)
        ast->base_expression = base_expression->clone(pool);
    if (postfix_expressions)
        ast->postfix_expressions = postfix_expressions->clone(pool);
    return ast;
}

void PostfixExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(base_expression, visitor);
        for (PostfixAST *fx = postfix_expressions; fx; fx = fx->next)
            accept(fx, visitor);
    }
    visitor->endVisit(this);
}

unsigned PostfixExpressionAST::firstToken() const
{
    return base_expression->firstToken();
}

unsigned PostfixExpressionAST::lastToken() const
{
    for (PostfixAST *it = postfix_expressions; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    return base_expression->lastToken();
}

QualifiedNameAST *QualifiedNameAST::clone(MemoryPool *pool) const
{
    QualifiedNameAST *ast = new (pool) QualifiedNameAST;
    ast->global_scope_token = global_scope_token;
    if (nested_name_specifier)
        ast->nested_name_specifier = nested_name_specifier->clone(pool);
    if (unqualified_name)
        ast->unqualified_name = unqualified_name->clone(pool);
    return ast;
}

void QualifiedNameAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(nested_name_specifier, visitor);
        accept(unqualified_name, visitor);
    }
    visitor->endVisit(this);
}

unsigned QualifiedNameAST::firstToken() const
{
    if (global_scope_token)
        return global_scope_token;
    else if (nested_name_specifier)
        return nested_name_specifier->firstToken();
    return unqualified_name->firstToken();
}

unsigned QualifiedNameAST::lastToken() const
{
    if (unqualified_name)
        return unqualified_name->lastToken();

    for (NestedNameSpecifierAST *it = nested_name_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (global_scope_token)
        return global_scope_token + 1;

    return 0;
}

ReferenceAST *ReferenceAST::clone(MemoryPool *pool) const
{
    ReferenceAST *ast = new (pool) ReferenceAST;
    ast->amp_token = amp_token;
    return ast;
}

void ReferenceAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned ReferenceAST::firstToken() const
{
    return amp_token;
}

unsigned ReferenceAST::lastToken() const
{
    return amp_token + 1;
}

ReturnStatementAST *ReturnStatementAST::clone(MemoryPool *pool) const
{
    ReturnStatementAST *ast = new (pool) ReturnStatementAST;
    ast->return_token = return_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void ReturnStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ReturnStatementAST::firstToken() const
{
    return return_token;
}

unsigned ReturnStatementAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (expression)
        return expression->lastToken();
    return return_token + 1;
}

SimpleDeclarationAST *SimpleDeclarationAST::clone(MemoryPool *pool) const
{
    SimpleDeclarationAST *ast = new (pool) SimpleDeclarationAST;
    if (decl_specifier_seq)
        ast->decl_specifier_seq = decl_specifier_seq->clone(pool);
    if (declarators)
        ast->declarators = declarators->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void SimpleDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = decl_specifier_seq; spec;
                 spec = spec->next)
            accept(spec, visitor);
        accept(declarators, visitor);
    }
    visitor->endVisit(this);
}

unsigned SimpleDeclarationAST::firstToken() const
{
    if (decl_specifier_seq)
        return decl_specifier_seq->firstToken();
    else if (declarators)
        return declarators->firstToken();
    return semicolon_token;
}

unsigned SimpleDeclarationAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;

    for (DeclaratorListAST *it = declarators; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    for (SpecifierAST *it = decl_specifier_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return 0;
}

SimpleNameAST *SimpleNameAST::clone(MemoryPool *pool) const
{
    SimpleNameAST *ast = new (pool) SimpleNameAST;
    ast->identifier_token = identifier_token;
    return ast;
}

void SimpleNameAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned SimpleNameAST::firstToken() const
{
    return identifier_token;
}

unsigned SimpleNameAST::lastToken() const
{
    return identifier_token + 1;
}

void SimpleSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

SimpleSpecifierAST *SimpleSpecifierAST::clone(MemoryPool *pool) const
{
    SimpleSpecifierAST *ast = new (pool) SimpleSpecifierAST;
    ast->specifier_token = specifier_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

unsigned SimpleSpecifierAST::firstToken() const
{
    return specifier_token;
}

unsigned SimpleSpecifierAST::lastToken() const
{
    return specifier_token + 1;
}

TypeofSpecifierAST *TypeofSpecifierAST::clone(MemoryPool *pool) const
{
    TypeofSpecifierAST *ast = new (pool) TypeofSpecifierAST;
    ast->typeof_token = typeof_token;
    if (expression)
        ast->expression = expression->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void TypeofSpecifierAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypeofSpecifierAST::firstToken() const
{
    return typeof_token;
}

unsigned TypeofSpecifierAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    return typeof_token + 1;
}

SizeofExpressionAST *SizeofExpressionAST::clone(MemoryPool *pool) const
{
    SizeofExpressionAST *ast = new (pool) SizeofExpressionAST;
    ast->sizeof_token = sizeof_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void SizeofExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned SizeofExpressionAST::firstToken() const
{
    return sizeof_token;
}

unsigned SizeofExpressionAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    return sizeof_token + 1;
}

StringLiteralAST *StringLiteralAST::clone(MemoryPool *pool) const
{
    StringLiteralAST *ast = new (pool) StringLiteralAST;
    ast->token = token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void StringLiteralAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(next, visitor);
    }
    visitor->endVisit(this);
}

unsigned StringLiteralAST::firstToken() const
{
    return token;
}

unsigned StringLiteralAST::lastToken() const
{
    if (next)
        return next->lastToken();
    return token + 1;
}

SwitchStatementAST *SwitchStatementAST::clone(MemoryPool *pool) const
{
    SwitchStatementAST *ast = new (pool) SwitchStatementAST;
    ast->switch_token = switch_token;
    ast->lparen_token = lparen_token;
    if (condition)
        ast->condition = condition->clone(pool);
    ast->rparen_token = rparen_token;
    if (statement)
        ast->statement = statement->clone(pool);
    return ast;
}

void SwitchStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(condition, visitor);
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned SwitchStatementAST::firstToken() const
{
    return switch_token;
}

unsigned SwitchStatementAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (condition)
        return condition->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    return switch_token + 1;
}

TemplateArgumentListAST *TemplateArgumentListAST::clone(MemoryPool *pool) const
{
    TemplateArgumentListAST *ast = new (pool) TemplateArgumentListAST;
    if (template_argument)
        ast->template_argument = template_argument->clone(pool);
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void TemplateArgumentListAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(template_argument, visitor);
        accept(next, visitor);
    }
    visitor->endVisit(this);
}

unsigned TemplateArgumentListAST::firstToken() const
{
    return template_argument->firstToken();
}

unsigned TemplateArgumentListAST::lastToken() const
{
    for (const TemplateArgumentListAST *it = this; it; it = it->next) {
        if (! it->next && it->template_argument)
            return it->template_argument->lastToken();
    }
    return 0;
}

TemplateDeclarationAST *TemplateDeclarationAST::clone(MemoryPool *pool) const
{
    TemplateDeclarationAST *ast = new (pool) TemplateDeclarationAST;
    ast->export_token = export_token;
    ast->template_token = template_token;
    ast->less_token = less_token;
    if (template_parameters)
        ast->template_parameters = template_parameters->clone(pool);
    ast->greater_token = greater_token;
    if (declaration)
        ast->declaration = declaration->clone(pool);
    return ast;
}

void TemplateDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (DeclarationAST *param = template_parameters; param;
                 param = param->next)
            accept(param, visitor);
        accept(declaration, visitor);
    }
    visitor->endVisit(this);
}

unsigned TemplateDeclarationAST::firstToken() const
{
    if (export_token)
        return export_token;
    return template_token;
}

unsigned TemplateDeclarationAST::lastToken() const
{
    if (declaration)
        return declaration->lastToken();
    else if (greater_token)
        return greater_token + 1;

    for (DeclarationAST *it = template_parameters; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (less_token)
        return less_token + 1;
    else if (template_token)
        return template_token + 1;
    else if (export_token)
        return export_token + 1;

    return 0;
}

TemplateIdAST *TemplateIdAST::clone(MemoryPool *pool) const
{
    TemplateIdAST *ast = new (pool) TemplateIdAST;
    ast->identifier_token = identifier_token;
    ast->less_token = less_token;
    if (template_arguments)
        ast->template_arguments = template_arguments->clone(pool);
    ast->greater_token = greater_token;
    return ast;
}

void TemplateIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) {
            accept(it, visitor);
        }
    }
    visitor->endVisit(this);
}

unsigned TemplateIdAST::firstToken() const
{
    return identifier_token;
}

unsigned TemplateIdAST::lastToken() const
{
    if (greater_token)
        return greater_token + 1;

    for (TemplateArgumentListAST *it = template_arguments; it; it = it->next) {
        if (! it->next && it->template_argument)
            return it->template_argument->lastToken();
    }

    if (less_token)
        return less_token + 1;

    return identifier_token + 1;
}

TemplateTypeParameterAST *TemplateTypeParameterAST::clone(MemoryPool *pool) const
{
    TemplateTypeParameterAST *ast = new (pool) TemplateTypeParameterAST;
    ast->template_token = template_token;
    ast->less_token = less_token;
    if (template_parameters)
        ast->template_parameters = template_parameters->clone(pool);
    ast->greater_token = greater_token;
    ast->class_token = class_token;
    if (name)
        ast->name = name->clone(pool);
    ast->equal_token = equal_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    return ast;
}

void TemplateTypeParameterAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned TemplateTypeParameterAST::firstToken() const
{
    return template_token;
}

unsigned TemplateTypeParameterAST::lastToken() const
{
    if (type_id)
        return type_id->lastToken();
    else if (equal_token)
        return equal_token + 1;
    else if (name)
        return name->lastToken();
    else if (class_token)
        return class_token + 1;
    else if (greater_token)
        return greater_token + 1;

    for (DeclarationAST *it = template_parameters; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (less_token)
        return less_token + 1;

    return template_token + 1;
}

ThisExpressionAST *ThisExpressionAST::clone(MemoryPool *pool) const
{
    ThisExpressionAST *ast = new (pool) ThisExpressionAST;
    ast->this_token = this_token;
    return ast;
}

void ThisExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned ThisExpressionAST::firstToken() const
{
    return this_token;
}

unsigned ThisExpressionAST::lastToken() const
{
    return this_token + 1;
}

ThrowExpressionAST *ThrowExpressionAST::clone(MemoryPool *pool) const
{
    ThrowExpressionAST *ast = new (pool) ThrowExpressionAST;
    ast->throw_token = throw_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void ThrowExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned ThrowExpressionAST::firstToken() const
{
    return throw_token;
}

unsigned ThrowExpressionAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    return throw_token + 1;
}

TranslationUnitAST *TranslationUnitAST::clone(MemoryPool *pool) const
{
    TranslationUnitAST *ast = new (pool) TranslationUnitAST;
    if (declarations)
        ast->declarations = declarations->clone(pool);
    return ast;
}

void TranslationUnitAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (DeclarationAST *decl = declarations; decl;
                 decl = decl->next)
            accept(decl, visitor);
    }
    visitor->endVisit(this);
}

unsigned TranslationUnitAST::firstToken() const
{
    return declarations->firstToken();
}

unsigned TranslationUnitAST::lastToken() const
{
    for (DeclarationAST *it = declarations; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }
    return 0;
}

TryBlockStatementAST *TryBlockStatementAST::clone(MemoryPool *pool) const
{
    TryBlockStatementAST *ast = new (pool) TryBlockStatementAST;
    ast->try_token = try_token;
    if (statement)
        ast->statement = statement->clone(pool);
    if (catch_clause_seq)
        ast->catch_clause_seq = catch_clause_seq->clone(pool);
    return ast;
}

void TryBlockStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(statement, visitor);
        accept(catch_clause_seq, visitor);
    }
    visitor->endVisit(this);
}

unsigned TryBlockStatementAST::firstToken() const
{
    return try_token;
}

unsigned TryBlockStatementAST::lastToken() const
{
    for (CatchClauseAST *it = catch_clause_seq; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (statement)
        return statement->lastToken();

    return try_token + 1;
}

TypeConstructorCallAST *TypeConstructorCallAST::clone(MemoryPool *pool) const
{
    TypeConstructorCallAST *ast = new (pool) TypeConstructorCallAST;
    if (type_specifier)
        ast->type_specifier = type_specifier->clone(pool);
    ast->lparen_token = lparen_token;
    if (expression_list)
        ast->expression_list = expression_list;
    ast->rparen_token = rparen_token;
    return ast;
}

void TypeConstructorCallAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        for (ExpressionListAST *expr = expression_list;expr;
                 expr = expr->next)
            accept(expr->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypeConstructorCallAST::firstToken() const
{
    return type_specifier->firstToken();
}

unsigned TypeConstructorCallAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;

    for (ExpressionListAST *it = expression_list; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (lparen_token)
        return lparen_token + 1;


    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return 0;
}

void TypeIdAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *spec = type_specifier; spec; spec = spec->next)
            accept(spec, visitor);
        accept(declarator, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypeIdAST::firstToken() const
{
    return type_specifier->firstToken();
}

unsigned TypeIdAST::lastToken() const
{
    if (declarator)
        return declarator->lastToken();

    for (SpecifierAST *it = type_specifier; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return 0;
}

TypeidExpressionAST *TypeidExpressionAST::clone(MemoryPool *pool) const
{
    TypeidExpressionAST *ast = new (pool) TypeidExpressionAST;
    ast->typeid_token = typeid_token;
    ast->lparen_token = lparen_token;
    if (expression)
        ast->expression = expression->clone(pool);
    ast->rparen_token = rparen_token;
    return ast;
}

void TypeidExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypeidExpressionAST::firstToken() const
{
    return typeid_token;
}

unsigned TypeidExpressionAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;
    else if (expression)
        return expression->lastToken();
    else if (lparen_token)
        return lparen_token + 1;

    return typeid_token + 1;
}

TypenameCallExpressionAST *TypenameCallExpressionAST::clone(MemoryPool *pool) const
{
    TypenameCallExpressionAST *ast = new (pool) TypenameCallExpressionAST;
    ast->typename_token = typename_token;
    if (name)
        ast->name = name->clone(pool);
    ast->lparen_token = lparen_token;
    if (expression_list)
        ast->expression_list = expression_list;
    ast->rparen_token = rparen_token;
    return ast;
}

void TypenameCallExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
        for (ExpressionListAST *expr = expression_list;expr;
                 expr = expr->next)
            accept(expr->expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypenameCallExpressionAST::firstToken() const
{
    return typename_token;
}

unsigned TypenameCallExpressionAST::lastToken() const
{
    if (rparen_token)
        return rparen_token + 1;

    for (ExpressionListAST *it = expression_list; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    if (lparen_token)
        return lparen_token + 1;
    else if (name)
        return name->lastToken();

    return typename_token + 1;
}

TypenameTypeParameterAST *TypenameTypeParameterAST::clone(MemoryPool *pool) const
{
    TypenameTypeParameterAST *ast = new (pool) TypenameTypeParameterAST;
    ast->classkey_token = classkey_token;
    if (name)
        ast->name = name->clone(pool);
    ast->equal_token = equal_token;
    if (type_id)
        ast->type_id = type_id->clone(pool);
    return ast;
}

void TypenameTypeParameterAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
        accept(type_id, visitor);
    }
    visitor->endVisit(this);
}

unsigned TypenameTypeParameterAST::firstToken() const
{
    return classkey_token;
}

unsigned TypenameTypeParameterAST::lastToken() const
{
    if (type_id)
        return type_id->lastToken();
    else if (equal_token)
        return equal_token + 1;
    else if (name)
        return name->lastToken();
    return classkey_token + 1;
}

UnaryExpressionAST *UnaryExpressionAST::clone(MemoryPool *pool) const
{
    UnaryExpressionAST *ast = new (pool) UnaryExpressionAST;
    ast->unary_op_token = unary_op_token;
    if (expression)
        ast->expression = expression->clone(pool);
    return ast;
}

void UnaryExpressionAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(expression, visitor);
    }
    visitor->endVisit(this);
}

unsigned UnaryExpressionAST::firstToken() const
{
    return unary_op_token;
}

unsigned UnaryExpressionAST::lastToken() const
{
    if (expression)
        return expression->lastToken();
    return unary_op_token + 1;
}

UsingAST *UsingAST::clone(MemoryPool *pool) const
{
    UsingAST *ast = new (pool) UsingAST;
    ast->using_token = using_token;
    ast->typename_token = typename_token;
    if (name)
        ast->name = name->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void UsingAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned UsingAST::firstToken() const
{
    return using_token;
}

unsigned UsingAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (name)
        return name->lastToken();
    else if (typename_token)
        return typename_token + 1;
    return using_token + 1;
}

UsingDirectiveAST *UsingDirectiveAST::clone(MemoryPool *pool) const
{
    UsingDirectiveAST *ast = new (pool) UsingDirectiveAST;
    ast->using_token = using_token;
    ast->namespace_token = namespace_token;
    if (name)
        ast->name = name->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void UsingDirectiveAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(name, visitor);
    }
    visitor->endVisit(this);
}

unsigned UsingDirectiveAST::firstToken() const
{
    return using_token;
}

unsigned UsingDirectiveAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;
    else if (name)
        return name->lastToken();
    else if (namespace_token)
        return namespace_token + 1;
    return using_token + 1;
}

WhileStatementAST *WhileStatementAST::clone(MemoryPool *pool) const
{
    WhileStatementAST *ast = new (pool) WhileStatementAST;
    ast->while_token = while_token;
    ast->lparen_token = lparen_token;
    if (condition)
        ast->condition = condition->clone(pool);
    ast->rparen_token = rparen_token;
    if (statement)
        ast->statement = statement->clone(pool);
    return ast;
}

void WhileStatementAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        accept(condition, visitor);
        accept(statement, visitor);
    }
    visitor->endVisit(this);
}

unsigned WhileStatementAST::firstToken() const
{
    return while_token;
}

unsigned WhileStatementAST::lastToken() const
{
    if (statement)
        return statement->lastToken();
    else if (rparen_token)
        return rparen_token + 1;
    else if (condition)
        return condition->lastToken();
    else if (lparen_token)
        return lparen_token + 1;
    return while_token + 1;
}

// ObjC++
unsigned IdentifierListAST::firstToken() const
{
    return identifier_token;
}

unsigned IdentifierListAST::lastToken() const
{
    for (const IdentifierListAST *it = this; it; it = it->next) {
        if (! it->next && it->identifier_token) {
            return it->identifier_token + 1;
        }
    }
    // ### assert?
    return 0;
}

IdentifierListAST *IdentifierListAST::clone(MemoryPool *pool) const
{
    IdentifierListAST *ast = new (pool) IdentifierListAST;
    ast->identifier_token = identifier_token;
    if (next)
        ast->next = next->clone(pool);
    return ast;
}

void IdentifierListAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
    }
    visitor->endVisit(this);
}

unsigned ObjCClassDeclarationAST::firstToken() const
{
    if (attributes)
        return attributes->firstToken();
    return class_token;
}

unsigned ObjCClassDeclarationAST::lastToken() const
{
    if (semicolon_token)
        return semicolon_token + 1;

    for (IdentifierListAST *it = identifier_list; it; it = it->next) {
        if (! it->next && it->identifier_token)
            return it->identifier_token + 1;
    }

    for (SpecifierAST *it = attributes; it; it = it->next) {
        if (! it->next)
            return it->lastToken();
    }

    return class_token + 1;
}

ObjCClassDeclarationAST *ObjCClassDeclarationAST::clone(MemoryPool *pool) const
{
    ObjCClassDeclarationAST *ast = new (pool) ObjCClassDeclarationAST;
    if (attributes)
        ast->attributes = attributes->clone(pool);
    ast->class_token = class_token;
    if (identifier_list)
        ast->identifier_list = identifier_list->clone(pool);
    ast->semicolon_token = semicolon_token;
    return ast;
}

void ObjCClassDeclarationAST::accept0(ASTVisitor *visitor)
{
    if (visitor->visit(this)) {
        for (SpecifierAST *it = attributes; it; it = it->next) {
            accept(it, visitor);
        }
    }
    visitor->endVisit(this);
}


CPLUSPLUS_END_NAMESPACE
