Parser.cpp 196 KB
Newer Older
con's avatar
con committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// 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 "Parser.h"
#include "Token.h"
#include "Lexer.h"
#include "Control.h"
#include "AST.h"
#include "Literals.h"
27
#include "ObjectiveCTypeQualifiers.h"
28
#include "QtContextKeywords.h"
29
#include <string>
Roberto Raggi's avatar
Roberto Raggi committed
30
#include <cstdio> // for putchar
31
#include <QDebug>
Tobias Hunger's avatar
Tobias Hunger committed
32
#ifdef _MSC_VER
Tobias Hunger's avatar
Tobias Hunger committed
33
#    define va_copy(dst, src) ((dst) = (src))
34 35
#elif defined(__INTEL_COMPILER) && !defined(va_copy)
#    define va_copy __va_copy
Tobias Hunger's avatar
Tobias Hunger committed
36 37
#endif

Roberto Raggi's avatar
Roberto Raggi committed
38
#define CPLUSPLUS_NO_DEBUG_RULE
39
#define MAX_EXPRESSION_DEPTH 100
40
#define MAX_STATEMENT_DEPTH 100
Roberto Raggi's avatar
Roberto Raggi committed
41

42 43
using namespace CPlusPlus;

Roberto Raggi's avatar
Roberto Raggi committed
44 45 46 47 48 49
namespace {

class DebugRule {
    static int depth;

public:
50
    DebugRule(const char *name, const char *spell, unsigned idx, bool blocked)
Roberto Raggi's avatar
Roberto Raggi committed
51
    {
52
        for (int i = 0; i <= depth; ++i)
53
          fputc('-', stderr);
Roberto Raggi's avatar
Roberto Raggi committed
54 55

        ++depth;
56
        fprintf(stderr, " %s, ahead: '%s' (%d) - block-errors: %d\n", name, spell, idx, blocked);
Roberto Raggi's avatar
Roberto Raggi committed
57
    }
Roberto Raggi's avatar
Roberto Raggi committed
58 59 60 61 62 63 64

    ~DebugRule()
    { --depth; }
};

int DebugRule::depth = 0;

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
inline bool lookAtAssignmentOperator(int tokenKind)
{
    switch (tokenKind) {
    case T_EQUAL:
    case T_AMPER_EQUAL:
    case T_CARET_EQUAL:
    case T_SLASH_EQUAL:
    case T_GREATER_GREATER_EQUAL:
    case T_LESS_LESS_EQUAL:
    case T_MINUS_EQUAL:
    case T_PERCENT_EQUAL:
    case T_PIPE_EQUAL:
    case T_PLUS_EQUAL:
    case T_STAR_EQUAL:
    case T_TILDE_EQUAL:
        return true;
    default:
        return false;
    } // switch
}

86
namespace Prec {
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
enum {
    Unknown         = 0,
    Comma           = 1,
    Assignment      = 2,
    Conditional     = 3,
    LogicalOr       = 4,
    LogicalAnd      = 5,
    InclusiveOr     = 6,
    ExclusiveOr     = 7,
    And             = 8,
    Equality        = 9,
    Relational      = 10,
    Shift           = 11,
    Additive        = 12,
    Multiplicative  = 13,
    PointerToMember = 14
};
104
} // namespace Precedece
105

106 107
inline int precedence(int tokenKind, bool templateArguments)
{
108 109
    // ### this will/might need some tuning for C++0x
    // (see: [temp.names]p3)
110
    if (templateArguments && (tokenKind == T_GREATER || tokenKind == T_GREATER_GREATER))
111 112
        return -1;

113
    if (lookAtAssignmentOperator(tokenKind))
114
        return Prec::Assignment;
115

116
    switch (tokenKind) {
117 118 119 120 121 122 123
    case T_COMMA:           return Prec::Comma;
    case T_QUESTION:        return Prec::Conditional;
    case T_PIPE_PIPE:       return Prec::LogicalOr;
    case T_AMPER_AMPER:     return Prec::LogicalAnd;
    case T_PIPE:            return Prec::InclusiveOr;
    case T_CARET:           return Prec::ExclusiveOr;
    case T_AMPER:           return Prec::And;
124
    case T_EQUAL_EQUAL:
125
    case T_EXCLAIM_EQUAL:   return Prec::Equality;
126 127 128
    case T_GREATER:
    case T_LESS:
    case T_LESS_EQUAL:
129
    case T_GREATER_EQUAL:   return Prec::Relational;
130
    case T_LESS_LESS:
131
    case T_GREATER_GREATER: return Prec::ExclusiveOr;
132
    case T_PLUS:
133
    case T_MINUS:           return Prec::Additive;
134 135
    case T_STAR:
    case T_SLASH:
136
    case T_PERCENT:         return Prec::Multiplicative;
137
    case T_ARROW_STAR:
138 139
    case T_DOT_STAR:        return Prec::PointerToMember;
    default:                return Prec::Unknown;
140 141 142
    }
}

143
inline bool isBinaryOperator(int tokenKind)
144 145 146 147 148 149 150
{ return precedence(tokenKind, false) != Prec::Unknown; }

inline bool isRightAssociative(int tokenKind)
{
    const int prec = precedence(tokenKind, false);
    return prec == Prec::Conditional || prec == Prec::Assignment;
}
151

Roberto Raggi's avatar
Roberto Raggi committed
152 153 154
} // end of anonymous namespace

#ifndef CPLUSPLUS_NO_DEBUG_RULE
155
#  define DEBUG_THIS_RULE() DebugRule __debug_rule__(__func__, tok().spell(), cursor(), _translationUnit->blockErrors())
Roberto Raggi's avatar
Roberto Raggi committed
156 157 158 159
#else
#  define DEBUG_THIS_RULE() do {} while (0)
#endif

160
#define PARSE_EXPRESSION_WITH_OPERATOR_PRECEDENCE(node, minPrecedence) { \
161 162 163 164
    if (LA() == T_THROW) { \
        if (!parseThrowExpression(node)) \
            return false; \
    } else if (!parseCastExpression(node)) \
165 166 167 168 169 170
        return false; \
    \
    parseExpressionWithOperatorPrecedence(node, minPrecedence); \
    return true; \
}

con's avatar
con committed
171 172 173 174 175 176 177
Parser::Parser(TranslationUnit *unit)
    : _translationUnit(unit),
      _control(_translationUnit->control()),
      _pool(_translationUnit->memoryPool()),
      _tokenIndex(1),
      _templateArguments(0),
      _qtMocRunEnabled(false),
178
      _cxx0xEnabled(false),
Roberto Raggi's avatar
Roberto Raggi committed
179 180
      _objCEnabled(false),
      _inFunctionBody(false),
Roberto Raggi's avatar
Roberto Raggi committed
181
      _inObjCImplementationContext(false),
182
      _inExpressionStatement(false),
183 184
      _expressionDepth(0),
      _statementDepth(0)
con's avatar
con committed
185 186 187 188 189 190 191 192 193 194 195
{ }

Parser::~Parser()
{ }

bool Parser::qtMocRunEnabled() const
{ return _qtMocRunEnabled; }

void Parser::setQtMocRunEnabled(bool onoff)
{ _qtMocRunEnabled = onoff; }

196 197 198
bool Parser::cxx0xEnabled() const
{ return _cxx0xEnabled; }

199
void Parser::setCxxOxEnabled(bool onoff)
200 201
{ _cxx0xEnabled = onoff; }

Roberto Raggi's avatar
Roberto Raggi committed
202 203 204 205 206 207
bool Parser::objCEnabled() const
{ return _objCEnabled; }

void Parser::setObjCEnabled(bool onoff)
{ _objCEnabled = onoff; }

con's avatar
con committed
208 209 210 211 212 213 214
bool Parser::switchTemplateArguments(bool templateArguments)
{
    bool previousTemplateArguments = _templateArguments;
    _templateArguments = templateArguments;
    return previousTemplateArguments;
}

215 216 217 218 219
bool Parser::maybeSplitGreaterGreaterToken(int n)
{
    return _translationUnit->maybeSplitGreaterGreaterToken(_tokenIndex + n - 1);
}

con's avatar
con committed
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
bool Parser::blockErrors(bool block)
{ return _translationUnit->blockErrors(block); }

bool Parser::skipUntil(int token)
{
    while (int tk = LA()) {
        if (tk == token)
            return true;

        consumeToken();
    }

    return false;
}

235
void Parser::skipUntilDeclaration()
con's avatar
con committed
236
{
237 238 239 240
    for (; ; consumeToken()) {
        switch (LA()) {
        case T_EOF_SYMBOL:

241 242 243
        // end of a block
        case T_RBRACE:

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
        // names
        case T_IDENTIFIER:
        case T_COLON_COLON:
        case T_TILDE:
        case T_OPERATOR:

        // empty declaration
        case T_SEMICOLON:

        // member specification
        case T_USING:
        case T_TEMPLATE:
        case T_PUBLIC:
        case T_PROTECTED:
        case T_PRIVATE:
        case T_Q_SIGNALS:
        case T_Q_SLOTS:
261
        case T_Q_PROPERTY:
262
        case T_Q_PRIVATE_PROPERTY:
263 264
        case T_Q_ENUMS:
        case T_Q_FLAGS:
265
        case T_Q_INTERFACES:
266 267 268 269 270

        // Qt function specifiers
        case T_Q_SIGNAL:
        case T_Q_SLOT:
        case T_Q_INVOKABLE:
271 272 273 274

        // declarations
        case T_ENUM:
        case T_NAMESPACE:
275 276
        case T_INLINE:
        case T_STATIC_ASSERT:
277 278
        case T_ASM:
        case T_EXPORT:
279 280 281 282 283
        case T_AT_CLASS:
        case T_AT_INTERFACE:
        case T_AT_PROTOCOL:
        case T_AT_IMPLEMENTATION:
        case T_AT_END:
284 285 286 287 288 289 290
            return;

        default:
            if (lookAtBuiltinTypeSpecifier() || lookAtClassKey() ||
                lookAtFunctionSpecifier() || lookAtStorageClassSpecifier())
                return;
        } // switch
291
    }
con's avatar
con committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
}

bool Parser::skipUntilStatement()
{
    while (int tk = LA()) {
        switch (tk) {
            case T_SEMICOLON:
            case T_LBRACE:
            case T_RBRACE:
            case T_CONST:
            case T_VOLATILE:
            case T_IDENTIFIER:
            case T_CASE:
            case T_DEFAULT:
            case T_IF:
            case T_SWITCH:
            case T_WHILE:
            case T_DO:
            case T_FOR:
            case T_BREAK:
            case T_CONTINUE:
            case T_RETURN:
            case T_GOTO:
            case T_TRY:
            case T_CATCH:
            case T_THROW:
            case T_CHAR:
319 320
            case T_CHAR16_T:
            case T_CHAR32_T:
con's avatar
con committed
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
            case T_WCHAR_T:
            case T_BOOL:
            case T_SHORT:
            case T_INT:
            case T_LONG:
            case T_SIGNED:
            case T_UNSIGNED:
            case T_FLOAT:
            case T_DOUBLE:
            case T_VOID:
            case T_CLASS:
            case T_STRUCT:
            case T_UNION:
            case T_ENUM:
            case T_COLON_COLON:
            case T_TEMPLATE:
            case T_USING:
                return true;

340 341
            case T_AT_SYNCHRONIZED:
                if (objCEnabled())
342
                    return true;
343

con's avatar
con committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
            default:
                consumeToken();
        }
    }

    return false;
}

bool Parser::skip(int l, int r)
{
    int count = 0;

    while (int tk = LA()) {
        if (tk == l)
            ++count;
        else if (tk == r)
            --count;
        else if (l != T_LBRACE && (tk == T_LBRACE ||
                                   tk == T_RBRACE ||
                                   tk == T_SEMICOLON))
            return false;

        if (count == 0)
            return true;

        consumeToken();
    }

    return false;
}

375 376 377 378 379 380 381 382 383 384 385 386
int Parser::find(int token, int stopAt)
{
    for (int i = 1; ; ++i) {
        const int tk = LA(i);
        if (!tk || tk == stopAt)
            return 0;
        if (tk == token)
            return i;
    }
    return 0;
}

con's avatar
con committed
387 388 389 390 391 392
void Parser::match(int kind, unsigned *token)
{
    if (LA() == kind)
        *token = consumeToken();
    else {
        *token = 0;
393
        error(_tokenIndex, "expected token `%s' got `%s'",
con's avatar
con committed
394 395 396 397 398 399
                                Token::name(kind), tok().spell());
    }
}

bool Parser::parseClassOrNamespaceName(NameAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
400
    DEBUG_THIS_RULE();
401
    if (LA() == T_IDENTIFIER && (LA(2) == T_COLON_COLON || LA(2) == T_LESS)) {
con's avatar
con committed
402 403
        unsigned identifier_token = cursor();

404 405 406 407 408 409 410 411
        if (LA(2) == T_LESS) {
            bool blocked = blockErrors(true);
            if (parseTemplateId(node) && LA() == T_COLON_COLON) {
                blockErrors(blocked);
                return true;
            }
            blockErrors(blocked);
        }
con's avatar
con committed
412 413 414 415 416 417 418 419 420 421 422

        rewind(identifier_token);

        if (LA(2) == T_COLON_COLON) {
            SimpleNameAST *ast = new (_pool) SimpleNameAST;
            ast->identifier_token = consumeToken();
            node = ast;
            return true;
        }
    } else if (LA() == T_TEMPLATE) {
        unsigned template_token = consumeToken();
423
        if (parseTemplateId(node, template_token) && LA() == T_COLON_COLON)
con's avatar
con committed
424 425 426 427 428 429
            return true;
        rewind(template_token);
    }
    return false;
}

430
bool Parser::parseTemplateId(NameAST *&node, unsigned template_token)
con's avatar
con committed
431
{
Roberto Raggi's avatar
Roberto Raggi committed
432
    DEBUG_THIS_RULE();
433 434 435

    const unsigned start = cursor();

con's avatar
con committed
436 437
    if (LA() == T_IDENTIFIER && LA(2) == T_LESS) {
        TemplateIdAST *ast = new (_pool) TemplateIdAST;
438
        ast->template_token = template_token;
con's avatar
con committed
439 440
        ast->identifier_token = consumeToken();
        ast->less_token = consumeToken();
441
        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateArgumentList(
Roberto Raggi's avatar
Roberto Raggi committed
442
                ast->template_argument_list)) {
443
            if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER) {
con's avatar
con committed
444 445 446 447 448 449
                ast->greater_token = consumeToken();
                node = ast;
                return true;
            }
        }
    }
450 451 452

    rewind(start);

con's avatar
con committed
453 454 455
    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
456
bool Parser::parseNestedNameSpecifier(NestedNameSpecifierListAST *&node,
con's avatar
con committed
457 458
                                      bool /*acceptTemplateId*/)
{
Roberto Raggi's avatar
Roberto Raggi committed
459
    DEBUG_THIS_RULE();
Roberto Raggi's avatar
Roberto Raggi committed
460
    NestedNameSpecifierListAST **nested_name_specifier = &node;
con's avatar
con committed
461
    NameAST *class_or_namespace_name = 0;
Roberto Raggi's avatar
Roberto Raggi committed
462
    if (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) {
con's avatar
con committed
463 464
        unsigned scope_token = consumeToken();

Roberto Raggi's avatar
Roberto Raggi committed
465 466 467 468 469
        NestedNameSpecifierAST *name = new (_pool) NestedNameSpecifierAST;
        name->class_or_namespace_name = class_or_namespace_name;
        name->scope_token = scope_token;

        *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name);
con's avatar
con committed
470 471
        nested_name_specifier = &(*nested_name_specifier)->next;

Roberto Raggi's avatar
Roberto Raggi committed
472
        while (parseClassOrNamespaceName(class_or_namespace_name) && LA() == T_COLON_COLON) {
con's avatar
con committed
473
            scope_token = consumeToken();
Roberto Raggi's avatar
Roberto Raggi committed
474 475 476 477 478 479

            name = new (_pool) NestedNameSpecifierAST;
            name->class_or_namespace_name = class_or_namespace_name;
            name->scope_token = scope_token;

            *nested_name_specifier = new (_pool) NestedNameSpecifierListAST(name);
con's avatar
con committed
480 481 482 483 484 485 486 487 488 489 490 491
            nested_name_specifier = &(*nested_name_specifier)->next;
        }

        // ### ugly hack
        rewind(scope_token);
        consumeToken();
        return true;
    }

    return false;
}

Roberto Raggi's avatar
Roberto Raggi committed
492
bool Parser::parseNestedNameSpecifierOpt(NestedNameSpecifierListAST *&name, bool acceptTemplateId)
con's avatar
con committed
493
{
Roberto Raggi's avatar
Roberto Raggi committed
494
    DEBUG_THIS_RULE();
con's avatar
con committed
495 496 497 498 499 500 501 502
    unsigned start = cursor();
    if (! parseNestedNameSpecifier(name, acceptTemplateId))
        rewind(start);
    return true;
}

bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
{
Roberto Raggi's avatar
Roberto Raggi committed
503
    DEBUG_THIS_RULE();
504
    unsigned global_scope_token = 0;
505 506 507 508 509 510 511 512 513 514 515 516

    switch (LA()) {
    case T_COLON_COLON:
    case T_IDENTIFIER:
    case T_TILDE: // destructor-name-id
    case T_OPERATOR: // operator-name-id
    case T_TEMPLATE: // template introduced template-id
      break;
    default:
      return false;
    }

con's avatar
con committed
517 518 519
    if (LA() == T_COLON_COLON)
        global_scope_token = consumeToken();

Roberto Raggi's avatar
Roberto Raggi committed
520
    NestedNameSpecifierListAST *nested_name_specifier = 0;
con's avatar
con committed
521 522 523 524 525 526 527 528 529 530 531 532 533
    parseNestedNameSpecifierOpt(nested_name_specifier,
                                /*acceptTemplateId=*/ true);

    NameAST *unqualified_name = 0;
    if (parseUnqualifiedName(unqualified_name,
                             /*acceptTemplateId=*/ acceptTemplateId || nested_name_specifier != 0)) {
        if (! global_scope_token && ! nested_name_specifier) {
            node = unqualified_name;
            return true;
        }

        QualifiedNameAST *ast = new (_pool) QualifiedNameAST;
        ast->global_scope_token = global_scope_token;
Roberto Raggi's avatar
Roberto Raggi committed
534
        ast->nested_name_specifier_list = nested_name_specifier;
con's avatar
con committed
535 536 537 538 539 540 541 542 543 544
        ast->unqualified_name = unqualified_name;
        node = ast;
        return true;
    }

    return false;
}

bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
545
    DEBUG_THIS_RULE();
con's avatar
con committed
546
    TranslationUnitAST *ast = new (_pool) TranslationUnitAST;
Roberto Raggi's avatar
Roberto Raggi committed
547
    DeclarationListAST **decl = &ast->declaration_list;
con's avatar
con committed
548 549 550 551

    while (LA()) {
        unsigned start_declaration = cursor();

Roberto Raggi's avatar
Roberto Raggi committed
552 553 554 555
        DeclarationAST *declaration = 0;

        if (parseDeclaration(declaration)) {
            *decl = new (_pool) DeclarationListAST;
556
            (*decl)->value = declaration;
Roberto Raggi's avatar
Roberto Raggi committed
557
            decl = &(*decl)->next;
con's avatar
con committed
558
        } else {
559
            error(start_declaration, "expected a declaration");
con's avatar
con committed
560 561 562
            rewind(start_declaration + 1);
            skipUntilDeclaration();
        }
Roberto Raggi's avatar
Roberto Raggi committed
563

564 565 566 567 568 569

        if (TopLevelDeclarationProcessor *processor = _control->topLevelDeclarationProcessor()) {
            if (processor->processDeclaration(declaration))
                break;
        }

Roberto Raggi's avatar
Roberto Raggi committed
570
        _templateArgumentList.clear();
con's avatar
con committed
571 572 573 574 575 576 577 578
    }

    node = ast;
    return true;
}

bool Parser::parseEmptyDeclaration(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
579
    DEBUG_THIS_RULE();
con's avatar
con committed
580 581 582 583 584 585 586 587 588 589 590
    if (LA() == T_SEMICOLON) {
        EmptyDeclarationAST *ast = new (_pool) EmptyDeclarationAST;
        ast->semicolon_token = consumeToken();
        node = ast;
        return true;
    }
    return false;
}

bool Parser::parseDeclaration(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
591
    DEBUG_THIS_RULE();
con's avatar
con committed
592 593 594 595 596 597 598 599 600 601 602 603 604
    switch (LA()) {
    case T_SEMICOLON:
        return parseEmptyDeclaration(node);

    case T_NAMESPACE:
        return parseNamespace(node);

    case T_USING:
        return parseUsing(node);

    case T_ASM:
        return parseAsmDefinition(node);

605

con's avatar
con committed
606 607 608 609
    case T_TEMPLATE:
    case T_EXPORT:
        return parseTemplateDeclaration(node);

Roberto Raggi's avatar
Roberto Raggi committed
610
    // ObjcC++
611 612
    case T_AT_CLASS:
        return parseObjCClassForwardDeclaration(node);
613

614 615
    case T_AT_INTERFACE:
        return parseObjCInterface(node);
616

617 618
    case T_AT_PROTOCOL:
        return parseObjCProtocol(node);
619

620 621
    case T_AT_IMPLEMENTATION:
        return parseObjCImplementation(node);
622

623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
    case T_Q_DECLARE_INTERFACE:
    {
        consumeToken();
        unsigned lparen_token = 0;
        match(T_LPAREN, &lparen_token);
        NameAST *name = 0;
        parseName(name);
        unsigned comma_token = 0;
        match(T_COMMA, &comma_token);
        unsigned string_literal = 0;
        match(T_STRING_LITERAL, &string_literal);
        unsigned rparen_token = 0;
        match(T_RPAREN, &rparen_token);
    }   return true;

638 639
    case T_AT_END:
        // TODO: should this be done here, or higher-up?
640
        error(cursor(), "skip stray token `%s'", tok().spell());
641 642
        consumeToken();
        break;
643

644 645 646
    case T_INLINE:
        if (_cxx0xEnabled && LA(2) == T_NAMESPACE)
            return parseNamespace(node);
647 648 649 650 651 652
        return parseSimpleDeclaration(node);

    case T_STATIC_ASSERT:
        if (_cxx0xEnabled)
            return parseStaticAssertDeclaration(node);
        return parseSimpleDeclaration(node);
653

Roberto Raggi's avatar
Roberto Raggi committed
654 655 656
    default: {
        if (_objCEnabled && LA() == T___ATTRIBUTE__) {
            const unsigned start = cursor();
Roberto Raggi's avatar
Roberto Raggi committed
657
            SpecifierListAST *attributes = 0, **attr = &attributes;
Roberto Raggi's avatar
Roberto Raggi committed
658 659
            while (parseAttributeSpecifier(*attr))
                attr = &(*attr)->next;
660 661 662 663 664 665
            if (LA() == T_AT_INTERFACE)
                return parseObjCInterface(node, attributes);
            else if (LA() == T_AT_PROTOCOL)
                return parseObjCProtocol(node, attributes);
            else if (LA() == T_AT_PROPERTY)
                return parseObjCPropertyDeclaration(node, attributes);
Roberto Raggi's avatar
Roberto Raggi committed
666 667
            rewind(start);
        }
668

con's avatar
con committed
669 670 671 672 673 674
        if (LA() == T_EXTERN && LA(2) == T_TEMPLATE)
            return parseTemplateDeclaration(node);
        else if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL)
            return parseLinkageSpecification(node);
        else
            return parseSimpleDeclaration(node);
Roberto Raggi's avatar
Roberto Raggi committed
675 676
    }   break; // default

con's avatar
con committed
677
    } // end switch
Roberto Raggi's avatar
Roberto Raggi committed
678 679

    return false;
con's avatar
con committed
680 681 682 683
}

bool Parser::parseLinkageSpecification(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
684
    DEBUG_THIS_RULE();
con's avatar
con committed
685 686 687
    if (LA() == T_EXTERN && LA(2) == T_STRING_LITERAL) {
        LinkageSpecificationAST *ast = new (_pool) LinkageSpecificationAST;
        ast->extern_token = consumeToken();
Roberto Raggi's avatar
cleanup  
Roberto Raggi committed
688
        ast->extern_type_token = consumeToken();
con's avatar
con committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703

        if (LA() == T_LBRACE)
            parseLinkageBody(ast->declaration);
        else
            parseDeclaration(ast->declaration);

        node = ast;
        return true;
    }

    return false;
}

bool Parser::parseLinkageBody(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
704
    DEBUG_THIS_RULE();
con's avatar
con committed
705 706 707
    if (LA() == T_LBRACE) {
        LinkageBodyAST *ast = new (_pool) LinkageBodyAST;
        ast->lbrace_token = consumeToken();
Roberto Raggi's avatar
Roberto Raggi committed
708
        DeclarationListAST **declaration_ptr = &ast->declaration_list;
con's avatar
con committed
709 710 711 712 713 714

        while (int tk = LA()) {
            if (tk == T_RBRACE)
                break;

            unsigned start_declaration = cursor();
Roberto Raggi's avatar
Roberto Raggi committed
715 716 717
            DeclarationAST *declaration = 0;
            if (parseDeclaration(declaration)) {
                *declaration_ptr = new (_pool) DeclarationListAST;
718
                (*declaration_ptr)->value = declaration;
Roberto Raggi's avatar
Roberto Raggi committed
719
                declaration_ptr = &(*declaration_ptr)->next;
con's avatar
con committed
720
            } else {
721
                error(start_declaration, "expected a declaration");
con's avatar
con committed
722 723 724
                rewind(start_declaration + 1);
                skipUntilDeclaration();
            }
Roberto Raggi's avatar
Roberto Raggi committed
725 726

            _templateArgumentList.clear();
con's avatar
con committed
727 728 729 730 731 732 733 734
        }
        match(T_RBRACE, &ast->rbrace_token);
        node = ast;
        return true;
    }
    return false;
}

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
bool Parser::parseStaticAssertDeclaration(DeclarationAST *&node)
{
    DEBUG_THIS_RULE();
    if (LA() != T_STATIC_ASSERT)
        return false;

    StaticAssertDeclarationAST *ast = new (_pool) StaticAssertDeclarationAST;
    ast->static_assert_token = consumeToken();
    match(T_LPAREN, &ast->lparen_token);
    parseConstantExpression(ast->expression);
    match(T_COMMA, &ast->comma_token);
    parseStringLiteral(ast->string_literal);
    match(T_RPAREN, &ast->rparen_token);
    match(T_SEMICOLON, &ast->semicolon_token);

    node = ast;
    return true;
}

con's avatar
con committed
754 755 756
// ### rename parseNamespaceAliarOrDeclaration?
bool Parser::parseNamespace(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
757
    DEBUG_THIS_RULE();
758
    if (LA() != T_NAMESPACE && !(_cxx0xEnabled && LA() == T_INLINE && LA(2) == T_NAMESPACE))
con's avatar
con committed
759 760
        return false;

761 762 763 764
    unsigned inline_token = 0;
    if (cxx0xEnabled() && LA() == T_INLINE)
        inline_token = consumeToken();

con's avatar
con committed
765 766 767
    unsigned namespace_token = consumeToken();

    if (LA() == T_IDENTIFIER && LA(2) == T_EQUAL) {
768 769
        if (inline_token)
            warning(inline_token, "namespace alias cannot be inline");
con's avatar
con committed
770 771 772
        NamespaceAliasDefinitionAST *ast =
                new (_pool) NamespaceAliasDefinitionAST;
        ast->namespace_token = namespace_token;
Roberto Raggi's avatar
cleanup  
Roberto Raggi committed
773
        ast->namespace_name_token = consumeToken();
con's avatar
con committed
774 775 776 777 778 779 780 781
        ast->equal_token = consumeToken();
        parseName(ast->name);
        match(T_SEMICOLON, &ast->semicolon_token);
        node = ast;
        return true;
    }

    NamespaceAST *ast = new (_pool) NamespaceAST;
782
    ast->inline_token = inline_token;
con's avatar
con committed
783 784 785
    ast->namespace_token = namespace_token;
    if (LA() == T_IDENTIFIER)
        ast->identifier_token = consumeToken();
Roberto Raggi's avatar
Roberto Raggi committed
786
    SpecifierListAST **attr_ptr = &ast->attribute_list;
con's avatar
con committed
787 788 789 790
    while (LA() == T___ATTRIBUTE__) {
        parseAttributeSpecifier(*attr_ptr);
        attr_ptr = &(*attr_ptr)->next;
    }
791
    if (LA() == T_LBRACE) {
con's avatar
con committed
792
        parseLinkageBody(ast->linkage_body);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
    } else { // attempt to do error recovery
        unsigned pos = cursor();
        for (;LA() != T_EOF_SYMBOL; consumeToken()) {
            switch (LA()) {
            case T_IDENTIFIER:
            case T_POUND:
            case T_POUND_POUND:
            case T___ATTRIBUTE__:
            case T_LPAREN:
            case T_RPAREN:
            case T_DEFAULT:
            case T_PUBLIC:
            case T_PRIVATE:
            case T_PROTECTED:
                continue;
            }
            if (tok().isLiteral())
                continue;
            break;
        }
        if (LA() == T_LBRACE && parseLinkageBody(ast->linkage_body))
            warning(pos, "expected '{' before '%s'", _translationUnit->tokenAt(pos).spell());
        else
            rewind(pos);
    }
con's avatar
con committed
818 819 820 821 822 823
    node = ast;
    return true;
}

bool Parser::parseUsing(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
824
    DEBUG_THIS_RULE();
con's avatar
con committed
825 826 827 828 829 830
    if (LA() != T_USING)
        return false;

    if (LA(2) == T_NAMESPACE)
        return parseUsingDirective(node);

831 832 833
    if (_cxx0xEnabled && LA(2) == T_IDENTIFIER && parseAliasDeclaration(node))
        return true;

con's avatar
con committed
834 835 836 837 838 839 840 841 842 843 844 845 846 847
    UsingAST *ast = new (_pool) UsingAST;
    ast->using_token = consumeToken();

    if (LA() == T_TYPENAME)
        ast->typename_token = consumeToken();

    parseName(ast->name);
    match(T_SEMICOLON, &ast->semicolon_token);
    node = ast;
    return true;
}

bool Parser::parseUsingDirective(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
848
    DEBUG_THIS_RULE();
con's avatar
con committed
849 850 851 852 853
    if (LA() == T_USING && LA(2) == T_NAMESPACE) {
        UsingDirectiveAST *ast = new (_pool) UsingDirectiveAST;
        ast->using_token = consumeToken();
        ast->namespace_token = consumeToken();
        if (! parseName(ast->name))
854 855
            warning(cursor(), "expected `namespace name' before `%s'",
                    tok().spell());
con's avatar
con committed
856 857 858 859 860 861 862
        match(T_SEMICOLON, &ast->semicolon_token);
        node = ast;
        return true;
    }
    return false;
}

863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
// alias-declaration = 'using' identifier attribute-specifier-seq(opt) '=' type-id ';'
bool Parser::parseAliasDeclaration(DeclarationAST *&node)
{
    DEBUG_THIS_RULE();
    if (LA() != T_USING || LA(2) != T_IDENTIFIER)
        return false;

    if (!find(T_EQUAL, T_SEMICOLON))
        return false;

    AliasDeclarationAST *alias = new (_pool) AliasDeclarationAST;
    alias->using_token = consumeToken();
    alias->identifier_token = consumeToken();

    // ### attributes!
    while (LA() != T_EQUAL)
        consumeToken();

    alias->equal_token = consumeToken();

    ExpressionAST *expr = 0;
    parseTypeId(expr);
    if (expr)
        alias->typeId = expr->asTypeId();

    match(T_SEMICOLON, &alias->semicolon_token);

    node = alias;
    return true;
}

con's avatar
con committed
894 895
bool Parser::parseConversionFunctionId(NameAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
896
    DEBUG_THIS_RULE();
con's avatar
con committed
897 898 899
    if (LA() != T_OPERATOR)
        return false;
    unsigned operator_token = consumeToken();
Roberto Raggi's avatar
Roberto Raggi committed
900
    SpecifierListAST *type_specifier = 0;
con's avatar
con committed
901 902 903
    if (! parseTypeSpecifier(type_specifier)) {
        return false;
    }
Roberto Raggi's avatar
Roberto Raggi committed
904
    PtrOperatorListAST *ptr_operators = 0, **ptr_operators_tail = &ptr_operators;
con's avatar
con committed
905 906 907 908 909
    while (parsePtrOperator(*ptr_operators_tail))
        ptr_operators_tail = &(*ptr_operators_tail)->next;

    ConversionFunctionIdAST *ast = new (_pool) ConversionFunctionIdAST;
    ast->operator_token = operator_token;
Roberto Raggi's avatar
Roberto Raggi committed
910 911
    ast->type_specifier_list = type_specifier;
    ast->ptr_operator_list = ptr_operators;
con's avatar
con committed
912 913 914 915 916 917
    node = ast;
    return true;
}

bool Parser::parseOperatorFunctionId(NameAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
918
    DEBUG_THIS_RULE();
con's avatar
con committed
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
    if (LA() != T_OPERATOR)
        return false;
    unsigned operator_token = consumeToken();

    OperatorAST *op = 0;
    if (! parseOperator(op))
        return false;

    OperatorFunctionIdAST *ast = new (_pool) OperatorFunctionIdAST;
    ast->operator_token = operator_token;
    ast->op = op;
    node = ast;
    return true;
}

934 935
Parser::TemplateArgumentListEntry *Parser::templateArgumentListEntry(unsigned tokenIndex)
{
Roberto Raggi's avatar
Roberto Raggi committed
936 937 938
    std::map<unsigned, TemplateArgumentListEntry>::iterator it =_templateArgumentList.find(tokenIndex);
    if (it != _templateArgumentList.end())
        return &it->second;
939 940 941 942

    return 0;
}

Roberto Raggi's avatar
Roberto Raggi committed
943
bool Parser::parseTemplateArgumentList(ExpressionListAST *&node)
con's avatar
con committed
944
{
945 946
    DEBUG_THIS_RULE();

947 948
    if (TemplateArgumentListEntry *entry = templateArgumentListEntry(cursor())) {
        rewind(entry->cursor);
Roberto Raggi's avatar
Roberto Raggi committed
949 950
        node = entry->ast;
        return entry->ast != 0;
951 952 953 954
    }

    unsigned start = cursor();

Roberto Raggi's avatar
Roberto Raggi committed
955
    ExpressionListAST **template_argument_ptr = &node;
con's avatar
con committed
956 957
    ExpressionAST *template_argument = 0;
    if (parseTemplateArgument(template_argument)) {
Roberto Raggi's avatar
Roberto Raggi committed
958
        *template_argument_ptr = new (_pool) ExpressionListAST;
959
        (*template_argument_ptr)->value = template_argument;
con's avatar
con committed
960
        template_argument_ptr = &(*template_argument_ptr)->next;
961 962 963 964

        if (_cxx0xEnabled && LA() == T_DOT_DOT_DOT)
            consumeToken(); // ### store this token in the AST

con's avatar
con committed
965
        while (LA() == T_COMMA) {
966
            consumeToken(); // consume T_COMMA
con's avatar
con committed
967 968

            if (parseTemplateArgument(template_argument)) {
Roberto Raggi's avatar
Roberto Raggi committed
969
                *template_argument_ptr = new (_pool) ExpressionListAST;
970
                (*template_argument_ptr)->value = template_argument;
con's avatar
con committed
971
                template_argument_ptr = &(*template_argument_ptr)->next;
972 973 974

                if (_cxx0xEnabled && LA() == T_DOT_DOT_DOT)
                    consumeToken(); // ### store this token in the AST
con's avatar
con committed
975 976
            }
        }
977

978 979
        if (_pool != _translationUnit->memoryPool()) {
            MemoryPool *pool = _translationUnit->memoryPool();
Roberto Raggi's avatar
Roberto Raggi committed
980 981
            ExpressionListAST *template_argument_list = node;
            for (ExpressionListAST *iter = template_argument_list, **ast_iter = &node;
982
                 iter; iter = iter->next, ast_iter = &(*ast_iter)->next)
Roberto Raggi's avatar
Roberto Raggi committed
983
                *ast_iter = new (pool) ExpressionListAST((iter->value) ? iter->value->clone(pool) : 0);
984 985
        }

986
        _templateArgumentList.insert(std::make_pair(start, TemplateArgumentListEntry(start, cursor(), node)));
con's avatar
con committed
987 988
        return true;
    }
989

990
    _templateArgumentList.insert(std::make_pair(start, TemplateArgumentListEntry(start, cursor(), 0)));
con's avatar
con committed
991 992 993 994 995
    return false;
}

bool Parser::parseAsmDefinition(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
996
    DEBUG_THIS_RULE();
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
    if (LA() != T_ASM)
        return false;

    AsmDefinitionAST *ast = new (_pool) AsmDefinitionAST;
    ast->asm_token = consumeToken();

    if (LA() == T_VOLATILE)
        ast->volatile_token = consumeToken();

    match(T_LPAREN, &ast->lparen_token);
    unsigned string_literal_token = 0;
    match(T_STRING_LITERAL, &string_literal_token);
    while (LA() == T_STRING_LITERAL) {
        consumeToken();
    }
    if (LA() == T_COLON) {
        consumeToken(); // skip T_COLON
        parseAsmOperandList();
        if (LA() == T_COLON) {
            consumeToken();
            parseAsmOperandList();
            if (LA() == T_COLON) {
                consumeToken();
                parseAsmClobberList();
            }
        } else if (LA() == T_COLON_COLON) {
            consumeToken();
            parseAsmClobberList();
        }
    } else if (LA() == T_COLON_COLON) {
        consumeToken();
1028
        parseAsmOperandList();
1029

1030 1031 1032 1033
        if (LA() == T_COLON) {
          consumeToken();
          parseAsmClobberList();
        }
1034 1035 1036 1037 1038 1039 1040 1041 1042
    }
    match(T_RPAREN, &ast->rparen_token);
    match(T_SEMICOLON, &ast->semicolon_token);
    node = ast;
    return true;
}

bool Parser::parseAsmOperandList()
{
Roberto Raggi's avatar
Roberto Raggi committed
1043
    DEBUG_THIS_RULE();
1044 1045 1046
    if (LA() != T_STRING_LITERAL)
        return true;

1047 1048 1049 1050
    if (parseAsmOperand()) {
        while (LA() == T_COMMA) {
            consumeToken();
            parseAsmOperand();
con's avatar
con committed
1051 1052 1053
        }
        return true;
    }
1054

con's avatar
con committed
1055 1056 1057
    return false;
}

1058 1059
bool Parser::parseAsmOperand()
{
Roberto Raggi's avatar
Roberto Raggi committed
1060
    DEBUG_THIS_RULE();
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
    unsigned string_literal_token = 0;
    match(T_STRING_LITERAL, &string_literal_token);

    if (LA() == T_LBRACKET) {
        /*unsigned lbracket_token = */ consumeToken();
        match(T_STRING_LITERAL, &string_literal_token);
        unsigned rbracket_token = 0;
        match(T_RBRACKET, &rbracket_token);
    }

    unsigned lparen_token = 0, rparen_token = 0;
    match(T_LPAREN, &lparen_token);
    ExpressionAST *expression = 0;
    parseExpression(expression);
    match(T_RPAREN, &rparen_token);
    return true;
}

bool Parser::parseAsmClobberList()
{
Roberto Raggi's avatar
Roberto Raggi committed
1081
    DEBUG_THIS_RULE();
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
    if (LA() != T_STRING_LITERAL)
        return false;

    unsigned string_literal_token = consumeToken();

    while (LA() == T_COMMA) {
        consumeToken();
        match(T_STRING_LITERAL, &string_literal_token);
    }

    return true;
}

con's avatar
con committed
1095 1096
bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
{
Roberto Raggi's avatar
Roberto Raggi committed
1097
    DEBUG_THIS_RULE();
con's avatar
con committed
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
    if (! (LA(1) == T_TEMPLATE || ((LA(1) == T_EXPORT || LA(1) == T_EXTERN)
            && LA(2) == T_TEMPLATE)))
        return false;

    TemplateDeclarationAST *ast = new (_pool) TemplateDeclarationAST;

    if (LA() == T_EXPORT || LA() == T_EXPORT)
        ast->export_token = consumeToken();

    ast->template_token = consumeToken();

    if (LA() == T_LESS) {
        ast->less_token = consumeToken();
1111
        if (maybeSplitGreaterGreaterToken() || LA() == T_GREATER || parseTemplateParameterList(ast->template_parameter_list))
con's avatar
con committed
1112 1113 1114
            match(T_GREATER, &ast->greater_token);
    }

1115
    while (LA()) {
1116 1117 1118 1119 1120 1121
        unsigned start_declaration = cursor();

        ast->declaration = 0;
        if (parseDeclaration(ast->declaration))
            break;

1122
        error(start_declaration, "expected a declaration");
1123 1124
        rewind(start_declaration + 1);
        skipUntilDeclaration();
1125
    }
1126

con's avatar
con committed
1127 1128 1129 1130 1131 1132
    node = ast;
    return true;
}

bool Parser::parseOperator(OperatorAST *&node) // ### FIXME
{
Roberto Raggi's avatar
Roberto Raggi committed
1133
    DEBUG_THIS_RULE();
con's avatar
con committed
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
    OperatorAST *ast = new (_pool) OperatorAST;

    switch (LA()) {
    case T_NEW:
    case T_DELETE: {
        ast->op_token = consumeToken();
        if (LA() == T_LBRACKET) {
            ast->open_token = consumeToken();
            match(T_RBRACKET, &ast->close_token);
        }
    } break;

    case T_PLUS:
    case T_MINUS:
    case T_STAR:
    case T_SLASH:
    case T_PERCENT:
    case T_CARET:
    case T_AMPER:
    case T_PIPE:
    case T_TILDE:
    case T_EXCLAIM:
    case T_LESS:
    case T_GREATER:
    case T_COMMA:
    case T_AMPER_EQUAL:
    case T_CARET_EQUAL:
    case T_SLASH_EQUAL:
    case T_EQUAL:
    case T_EQUAL_EQUAL:
    case T_EXCLAIM_EQUAL:
    case T_GREATER_EQUAL:
    case T_GREATER_GREATER_EQUAL:
    case T_LESS_EQUAL:
    case T_LESS_LESS_EQUAL:
    case T_MINUS_EQUAL:
    case T_PERCENT_EQUAL:
    case T_PIPE_EQUAL:
    case T_PLUS_EQUAL:
    case T_STAR_EQUAL:
    case T_TILDE_EQUAL:
    case T_LESS_LESS:
    case T_GREATER_GREATER:
    case T_AMPER_AMPER:
    case T_PIPE_PIPE:
    case T_PLUS_PLUS:
    case T_MINUS_MINUS:
    case T_ARROW_STAR:
    case T_DOT_STAR:
    case T_ARROW:
        ast->op_token = consumeToken();
        break;

    default:
        if (LA() == T_LPAREN && LA(2) == T_RPAREN) {
            ast->op_token = ast->open_token = consumeToken();
            ast->close_token = consumeToken();
        } else if (LA() == T_LBRACKET && LA(2) == T_RBRACKET) {
            ast->op_token = ast->open_token = consumeToken();
            ast->close_token = consumeToken();
        } else {