diff options
Diffstat (limited to 'shared/cplusplus/Parser.cpp')
-rw-r--r-- | shared/cplusplus/Parser.cpp | 703 |
1 files changed, 302 insertions, 401 deletions
diff --git a/shared/cplusplus/Parser.cpp b/shared/cplusplus/Parser.cpp index 8e15a220be..6911fd4f9c 100644 --- a/shared/cplusplus/Parser.cpp +++ b/shared/cplusplus/Parser.cpp @@ -403,39 +403,45 @@ bool Parser::parseDeclaration(DeclarationAST *&node) case T_EXPORT: return parseTemplateDeclaration(node); - // objc++ - case T_AT_IMPLEMENTATION: - return parseObjCClassImplementation(node); - + // ObjcC++ case T_AT_CLASS: return parseObjCClassDeclaration(node); case T_AT_INTERFACE: - return parseObjCInterfaceDeclaration(node); + return parseObjCInterface(node); case T_AT_PROTOCOL: - return parseObjCProtocolDeclaration(node); + return parseObjCProtocol(node); case T_AT_END: - return parseObjCEndDeclaration(node); - - case T_AT_COMPATIBILITY_ALIAS: - return parseObjCAliasDeclaration(node); - - case T_AT_SYNTHESIZE: - return parseObjCPropertySynthesize(node); + return parseObjCEnd(node); - case T_AT_DYNAMIC: - return parseObjCPropertyDynamic(node); + default: { + if (_objCEnabled && LA() == T___ATTRIBUTE__) { + const unsigned start = cursor(); + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + 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); + rewind(start); + } - default: 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); + } break; // default + } // end switch + + return false; } bool Parser::parseLinkageSpecification(DeclarationAST *&node) @@ -2543,16 +2549,7 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node) case T_SLOT: return parseQtMethod(node); - case T_AT_ENCODE: - case T_AT_PROTOCOL: - case T_AT_SELECTOR: - case T_AT_STRING_LITERAL: - return parseObjCExpression(node); - default: { - if (_objCEnabled && LA() == T_LBRACKET) - return parseObjCExpression(node); - unsigned startOfName = cursor(); NameAST *name = 0; if (parseName(name)) { @@ -3303,513 +3300,417 @@ bool Parser::parseThrowExpression(ExpressionAST *&node) return false; } -bool Parser::parseObjCClassImplementation(DeclarationAST *&) +bool Parser::lookAtObjCSelector() const { - if (LA() != T_AT_IMPLEMENTATION) - return false; - - /*unsigned implementation_token = */ consumeToken(); - unsigned identifier_token = 0; - match(T_IDENTIFIER, &identifier_token); + switch (LA()) { + case T_IDENTIFIER: + case T_OR: + case T_AND: + case T_NOT: + case T_XOR: + case T_BITOR: + case T_COMPL: + case T_OR_EQ: + case T_AND_EQ: + case T_BITAND: + case T_NOT_EQ: + case T_XOR_EQ: + return true; - if (LA() == T_COLON) { - /*unsigned colon_token = */ consumeToken(); - unsigned superclass_name_token = 0; - match(T_IDENTIFIER, &superclass_name_token); - } else if (LA() == T_LPAREN) { - /*unsigned lparen_token = */ consumeToken(); - unsigned category_name_token = 0; - if (LA() == T_IDENTIFIER) - category_name_token = consumeToken(); - unsigned rparen_token = 0; - match(T_RPAREN, &rparen_token); - } + default: + if (tok().isKeyword()) + return true; + } // switch - _inObjCImplementationContext = true; - parseObjCMethodDefinitionList(); - return true; + return false; } +// objc-class-declaraton ::= T_AT_CLASS (T_IDENTIFIER @ T_COMMA) T_SEMICOLON +// bool Parser::parseObjCClassDeclaration(DeclarationAST *&node) { if (LA() != T_AT_CLASS) return false; - ObjCClassDeclarationAST *ast = new (_pool) ObjCClassDeclarationAST; - ast->class_token = consumeToken(); - parseObjCIdentifierList(ast->identifier_list); - match(T_SEMICOLON, &ast->semicolon_token); - node = ast; + unsigned objc_class_token = consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + while (LA() == T_COMMA) { + consumeToken(); // skip T_COMMA + match(T_IDENTIFIER, &identifier_token); + } + + unsigned semicolon_token = 0; + match(T_SEMICOLON, &semicolon_token); return true; } -bool Parser::parseObjCInterfaceDeclaration(DeclarationAST *&) +// objc-interface ::= attribute-specifier-list-opt objc-class-interface +// objc-interface ::= objc-category-interface +// +// objc-class-interface ::= T_AT_INTERFACE T_IDENTIFIER (T_COLON T_IDENTIFIER)? +// objc-protocol-refs-opt +// objc-class-instance-variables-opt +// objc-interface-declaration-list +// T_AT_END +// +// objc-category-interface ::= T_AT_INTERFACE T_IDENTIFIER +// T_LPAREN T_IDENTIFIER? T_RPAREN +// objc-protocol-refs-opt +// objc-interface-declaration-list +// T_AT_END +// +bool Parser::parseObjCInterface(DeclarationAST *&node, + SpecifierAST *attributes) { + if (! attributes && LA() == T___ATTRIBUTE__) { + SpecifierAST **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + } + if (LA() != T_AT_INTERFACE) return false; - /*unsigned interface_token = */ consumeToken(); - unsigned interface_name_token = 0; - match(T_IDENTIFIER, &interface_name_token); + unsigned objc_interface_token = consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + if (LA() == T_LPAREN) { - // category interface - /*unsigned lparen_token = */ consumeToken(); - unsigned catagory_name_token = 0; + // a category interface + + if (attributes) + _translationUnit->error(attributes->firstToken(), + "invalid attributes for category interface declaration"); + + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); if (LA() == T_IDENTIFIER) - catagory_name_token = consumeToken(); - unsigned rparen_token = 0; + consumeToken(); + match(T_RPAREN, &rparen_token); + parseObjCProtocolRefs(); - parseObjCClassInstanceVariables(); - parseObjCInterfaceDeclList(); - unsigned end_token = 0; - match(T_AT_END, &end_token); - return true; - } else { - // class interface - unsigned colon_token = 0; - unsigned super_class_token = 0; - if (LA() == T_COLON) { - colon_token = consumeToken(); - match(T_IDENTIFIER, &super_class_token); + while (parseObjCInterfaceMemberDeclaration()) { } - parseObjCProtocolRefs(); - parseObjCInterfaceDeclList(); - unsigned end_token = 0; - match(T_AT_END, &end_token); + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); return true; } - return false; -} - -bool Parser::parseObjCProtocolDeclaration(DeclarationAST *&) -{ - return false; -} - -bool Parser::parseObjCEndDeclaration(DeclarationAST *&) -{ - if (LA() != T_AT_END) - return false; - - unsigned end_token = consumeToken(); - if (! _inObjCImplementationContext) { - _translationUnit->warning(end_token, - "@end must appear in an @implementation context"); + // a class interface declaration + if (LA() == T_COLON) { + consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); } - _inObjCImplementationContext = false; + parseObjCProtocolRefs(); + parseObjClassInstanceVariables(); + while (parseObjCInterfaceMemberDeclaration()) { + } + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); return true; } -bool Parser::parseObjCAliasDeclaration(DeclarationAST *&) +// objc-protocol ::= T_AT_PROTOCOL (T_IDENTIFIER @ T_COMMA) T_SEMICOLON +// +bool Parser::parseObjCProtocol(DeclarationAST *&node, + SpecifierAST *attributes) { - return false; -} + if (! attributes && LA() == T___ATTRIBUTE__) { + SpecifierAST **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + } -bool Parser::parseObjCPropertySynthesize(DeclarationAST *&) -{ - return false; -} + if (LA() != T_AT_PROTOCOL) + return false; -bool Parser::parseObjCPropertyDynamic(DeclarationAST *&) -{ - return false; -} + unsigned objc_protocol_token = consumeToken(); + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + + if (LA() == T_COMMA || LA() == T_SEMICOLON) { + // a protocol forward declaration -bool Parser::parseObjCIdentifierList(IdentifierListAST *&node) -{ - if (LA() == T_IDENTIFIER) { - IdentifierListAST **it = &node; - IdentifierListAST *id = new (_pool) IdentifierListAST; - id->identifier_token = consumeToken(); - *it = id; while (LA() == T_COMMA) { consumeToken(); - if (LA() == T_IDENTIFIER) { - it = &(*it)->next; - IdentifierListAST *id = new (_pool) IdentifierListAST; - id->identifier_token = consumeToken(); - *it = id; - } + match(T_IDENTIFIER, &identifier_token); } + unsigned semicolon_token = 0; + match(T_SEMICOLON, &semicolon_token); return true; } - return false; -} -bool Parser::parseObjCProtocolRefs() -{ - return false; -} + // a protocol definition + parseObjCProtocolRefs(); -bool Parser::parseObjCClassInstanceVariables() -{ - return false; -} - -bool Parser::parseObjCInterfaceDeclList() -{ - unsigned saved = cursor(); - while (LA() != T_AT_END && parseObjCInterfaceMemberDeclaration()) { - if (saved == cursor()) - consumeToken(); // skip a token + while (parseObjCInterfaceMemberDeclaration()) { } - return true; -} - -bool Parser::parseObjCInterfaceMemberDeclaration() -{ - switch (LA()) { - case T_SEMICOLON: - consumeToken(); - return true; - - case T_AT_REQUIRED: - case T_AT_OPTIONAL: - consumeToken(); - return true; - - case T_PLUS: - case T_MINUS: - return parseObjCMethodPrototype(); - - default: { - DeclarationAST *declaration = 0; - if (parseDeclaration(declaration)) - return true; - } // default - } // switch + unsigned objc_end_token = 0; + match(T_AT_END, &objc_end_token); - return false; + return true; } -bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&) -{ - return false; -} -bool Parser::parseObjCMethodPrototype() +// objc-protocol-refs ::= T_LESS (T_IDENTIFIER @ T_COMMA) T_GREATER +// +bool Parser::parseObjCProtocolRefs() { - if (LA() != T_PLUS && LA() != T_MINUS) + if (LA() != T_LESS) return false; - - // instance or class method? - /*unsigned method_type_token = */ consumeToken(); - - SpecifierAST *attributes = 0, **attr = &attributes; - while (parseAttributeSpecifier(*attr)) - attr = &(*attr)->next; - - return false; + unsigned less_token = 0, greater_token = 0; + unsigned identifier_token = 0; + match(T_LESS, &less_token); + match(T_IDENTIFIER, &identifier_token); + while (LA() == T_COMMA) { + consumeToken(); + match(T_IDENTIFIER, &identifier_token); + } + match(T_GREATER, &greater_token); + return true; } -bool Parser::parseObjCExpression(ExpressionAST *&node) +// objc-class-instance-variables ::= T_LBRACE +// objc-instance-variable-decl-list-opt +// T_RBRACE +// +bool Parser::parseObjClassInstanceVariables() { - switch (LA()) { - case T_LBRACKET: - return parseObjCMessageExpression(node); + if (LA() != T_LBRACE) + return false; - case T_AT_STRING_LITERAL: - return parseObjCStringLiteral(node); + unsigned lbrace_token = 0, rbrace_token = 0; - case T_AT_ENCODE: - return parseObjCEncodeExpression(node); + match(T_LBRACE, &lbrace_token); + while (LA()) { + if (LA() == T_RBRACE) + break; - case T_AT_PROTOCOL: - return parseObjCProtocolExpression(node); + const unsigned start = cursor(); - case T_AT_SELECTOR: - return parseObjCSelectorExpression(node); - } - return false; -} + DeclarationAST *declaration = 0; + parseObjCInstanceVariableDeclaration(declaration); -bool Parser::parseObjCMessageExpression(ExpressionAST *&) -{ - if (LA() != T_LBRACKET) - return false; + if (start == cursor()) { + // skip stray token. + _translationUnit->error(cursor(), "skip stray token `%s'", tok().spell()); + consumeToken(); + } + } - /*unsigned lbracket_token = */ consumeToken(); - ExpressionAST *receiver = 0; - parseObjCMessageReceiver(receiver); - parseObjCMessageArguments(); - unsigned rbracket_token = 0; - match(T_RBRACKET, &rbracket_token); + match(T_RBRACE, &rbrace_token); return true; } -bool Parser::parseObjCStringLiteral(ExpressionAST *&) +// objc-interface-declaration ::= T_AT_REQUIRED +// objc-interface-declaration ::= T_AT_OPTIONAL +// objc-interface-declaration ::= T_SEMICOLON +// objc-interface-declaration ::= objc-property-declaration +// objc-interface-declaration ::= objc-method-prototype +bool Parser::parseObjCInterfaceMemberDeclaration() { - if (LA() != T_AT_STRING_LITERAL) - return false; - - do { + switch (LA()) { + case T_AT_REQUIRED: + case T_AT_OPTIONAL: consumeToken(); - } while (LA() == T_AT_STRING_LITERAL); + return true; - return true; -} + case T_SEMICOLON: + consumeToken(); + return true; -bool Parser::parseObjCEncodeExpression(ExpressionAST *&) -{ - if (LA() != T_AT_ENCODE) - return false; + case T_AT_PROPERTY: { + DeclarationAST *declaration = 0; + return parseObjCPropertyDeclaration(declaration); + } - /*unsigned encode_token = */ consumeToken(); - unsigned lparen_token = 0, rparen_token = 0; - match(T_LPAREN, &lparen_token); - SpecifierAST *type_specifier = 0; - parseSimpleTypeSpecifier(type_specifier); - match(T_RPAREN, &rparen_token); - return true; -} + case T_PLUS: + case T_MINUS: + return parseObjCMethodPrototype(); -bool Parser::parseObjCProtocolExpression(ExpressionAST *&) -{ - if (LA() != T_AT_PROTOCOL) + default: return false; - - /*unsigned protocol_token = */ consumeToken(); - unsigned protocol_name_token = 0, lparen_token = 0, rparen_token = 0; - match(T_LPAREN, &lparen_token); - match(T_IDENTIFIER, &protocol_name_token); - match(T_RPAREN, &rparen_token); - return true; + } } -bool Parser::parseObjCSelectorExpression(ExpressionAST *&) +// objc-instance-variable-declaration ::= objc-visibility-specifier +// objc-instance-variable-declaration ::= block-declaration +// +bool Parser::parseObjCInstanceVariableDeclaration(DeclarationAST *&node) { - if (LA() != T_AT_SELECTOR) - return false; + switch (LA()) { + case T_AT_PRIVATE: + case T_AT_PROTECTED: + case T_AT_PUBLIC: + case T_AT_PACKAGE: + consumeToken(); + return true; - /*unsigned selector_token = */ consumeToken(); - unsigned lparen_token = 0, rparen_token = 0; - match(T_LPAREN, &lparen_token); - while (LA(1) == T_IDENTIFIER && LA(2) == T_COLON) { - /*unsigned identifier_token = */ consumeToken(); - /*unsigned colon_token = */ consumeToken(); + default: + return parseBlockDeclaration(node); } - match(T_RPAREN, &rparen_token); - return true; -} - -bool Parser::parseObjCMessageReceiver(ExpressionAST *&node) -{ - // ### expression or simple-type-specifier. - return parseExpression(node); } -bool Parser::parseObjCMessageArguments() +// objc-property-declaration ::= +// T_AT_PROPERTY T_LPAREN (property-attribute @ T_COMMA) T_RPAREN simple-declaration +// +bool Parser::parseObjCPropertyDeclaration(DeclarationAST *&, SpecifierAST *) { - if (LA() != T_IDENTIFIER && LA() != T_COLON) + if (LA() != T_AT_PROPERTY) return false; - unsigned selector_name_token = 0; - - if (LA() == T_IDENTIFIER) - selector_name_token = consumeToken(); - - if (LA() == T_COLON) { - /*unsigned colon_token = */ consumeToken(); - - ExpressionAST *expr = 0; - parseAssignmentExpression(expr); - - while ((LA() == T_IDENTIFIER && LA(2) == T_COLON) || LA() == T_COLON) { - if (LA() == T_IDENTIFIER) - consumeToken(); + unsigned objc_property_token = consumeToken(); - if (LA() == T_COLON) - consumeToken(); - - parseAssignmentExpression(expr); - } - - while (LA() == T_COMMA) { - consumeToken(); - parseAssignmentExpression(expr); + if (LA() == T_LPAREN) { + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); + while (parseObjCPropertyAttribute()) { } + match(T_RPAREN, &rparen_token); } + DeclarationAST *simple_declaration = 0; + parseSimpleDeclaration(simple_declaration, /*accept-struct-declarators = */ false); return true; } -bool Parser::parseObjCMethodDefinitionList() +// objc-method-prototype ::= (T_PLUS | T_MINUS) objc-method-decl objc-method-attrs-opt +// +// objc-method-decl ::= objc-type-name? objc-selector +// objc-method-decl ::= objc-type-name? objc-keyword-decl-list objc-parmlist-opt +// +bool Parser::parseObjCMethodPrototype() { - bool done = false; - while (! done) { - switch (LA()) { - case T_EOF_SYMBOL: - case T_AT_END: - done = true; - break; + if (LA() != T_PLUS && LA() != T_MINUS) + return false; - case T_PLUS: - case T_MINUS: - parseObjCMethodSignature(); - if (LA() == T_SEMICOLON) - consumeToken(); - break; + unsigned method_type_token = consumeToken(); - case T_AT_PROPERTY: - parseObjCAtProperty(); - break; - - case T_SEMICOLON: - consumeToken(); - break; + parseObjCTypeName(); - case T_AT_OPTIONAL: - consumeToken(); - break; + if ((lookAtObjCSelector() && LA(2) == T_COLON) || LA() == T_COLON) { + while (parseObjCKeywordDeclaration()) { + } - case T_AT_REQUIRED: + while (LA() == T_COMMA) { consumeToken(); - break; - case T_TEMPLATE: - case T_NAMESPACE: { - DeclarationAST *declaration = 0; - parseDeclaration(declaration); - } break; - - default: { - unsigned start = cursor(); - DeclarationAST *declaration = 0; - if (LA(1) == T_EXTERN && LA(2) == T_STRING_LITERAL) { - parseLinkageSpecification(declaration); - } else if (parseBlockDeclaration(declaration)) { - // ### accept the declaration. - } else { - if (cursor() == start) { - _translationUnit->error(cursor(), - "stray `%s' between Objective-C++ methods", - tok().spell()); - consumeToken(); - } + if (LA() == T_DOT_DOT_DOT) { + consumeToken(); + break; } - } break; // default - } // switch + DeclarationAST *parameter_declaration = 0; + parseParameterDeclaration(parameter_declaration); + } + } else if (lookAtObjCSelector()) { + parseObjCSelector(); + } else { + _translationUnit->error(cursor(), "expected a selector"); } + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + return true; } -bool Parser::parseObjCMethodSignature() +// objc-property-attribute ::= getter '=' identifier +// objc-property-attribute ::= setter '=' identifier ':' +// objc-property-attribute ::= readonly +// objc-property-attribute ::= readwrite +// objc-property-attribute ::= assign +// objc-property-attribute ::= retain +// objc-property-attribute ::= copy +// objc-property-attribute ::= nonatomic +bool Parser::parseObjCPropertyAttribute() { - if (LA() != T_PLUS && LA() != T_MINUS) + if (LA() != T_IDENTIFIER) return false; - /*unsigned method_type_token = */ consumeToken(); - parseObjCTypeName(); - - bool first = true; - - while (lookAtObjCSelector() || LA() == T_COLON) { - if (LA() != T_COLON) - /*selector_name_token = */ consumeToken(); - - SpecifierAST *attributes = 0, **attr = &attributes; - while (parseAttributeSpecifier(*attr)) - attr = &(*attr)->next; - - if (first) { - first = false; - - if (LA() != T_COLON) - break; - } - - unsigned colon_token = 0; - match(T_COLON, &colon_token); - - parseObjCTypeName(); - - unsigned identifier_token = 0; - match(T_IDENTIFIER, &identifier_token); - - while (parseAttributeSpecifier(*attr)) - attr = &(*attr)->next; - } - - // parse the method tail parameters. - while (LA() == T_COMMA) { + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + if (LA() == T_EQUAL) { consumeToken(); - - if (LA() == T_DOT_DOT_DOT) { + match(T_IDENTIFIER, &identifier_token); + if (LA() == T_COLON) consumeToken(); - break; - } - - DeclarationAST *parameter_declaration = 0; - parseParameterDeclaration(parameter_declaration); } return true; } +// objc-type-name ::= T_LPAREN objc-type-qualifiers-opt type-id T_RPAREN +// bool Parser::parseObjCTypeName() { if (LA() != T_LPAREN) return false; - /*unsigned lparen_token = */ consumeToken(); - - parseObjCProtocolQualifiers(); - + unsigned lparen_token = 0, rparen_token = 0; + match(T_LPAREN, &lparen_token); + parseObjCTypeQualifiers(); ExpressionAST *type_id = 0; - if (LA() != T_RPAREN) - parseTypeId(type_id); + parseTypeId(type_id); + match(T_RPAREN, &rparen_token); + return true; +} - SpecifierAST *attributes = 0, **attr = &attributes; - while (parseAttributeSpecifier(*attr)) - attr = &(*attr)->next; +// objc-selector ::= T_IDENTIFIER | keyword +// +bool Parser::parseObjCSelector() +{ + if (! lookAtObjCSelector()) + return false; - unsigned rparen_token = 0; - match(T_RPAREN, &rparen_token); + consumeToken(); return true; } -bool Parser::parseObjCAtProperty() +// objc-keyword-decl ::= objc-selector? T_COLON objc-type-name? objc-keyword-attributes-opt T_IDENTIFIER +// +bool Parser::parseObjCKeywordDeclaration() { - if (LA() != T_AT_PROPERTY) + if (! (LA() == T_COLON || (lookAtObjCSelector() && LA(2) == T_COLON))) return false; - /*unsigned property_token = */ consumeToken(); + parseObjCSelector(); + + unsigned colon_token = 0; + match(T_COLON, &colon_token); + + parseObjCTypeName(); + + SpecifierAST *attributes = 0, **attr = &attributes; + while (parseAttributeSpecifier(*attr)) + attr = &(*attr)->next; + + unsigned identifier_token = 0; + match(T_IDENTIFIER, &identifier_token); + return true; } -bool Parser::parseObjCProtocolQualifiers() +bool Parser::parseObjCTypeQualifiers() { return false; } -bool Parser::lookAtObjCSelector() const +// objc-end: T_AT_END +bool Parser::parseObjCEnd(DeclarationAST *&) { - switch (LA()) { - case T_IDENTIFIER: - case T_OR: - case T_AND: - case T_NOT: - case T_XOR: - case T_BITOR: - case T_COMPL: - case T_OR_EQ: - case T_AND_EQ: - case T_BITAND: - case T_NOT_EQ: - case T_XOR_EQ: - return true; - - default: - if (tok().isKeyword()) - return true; - } // switch + if (LA() != T_AT_END) + return false; - return false; + consumeToken(); + return true; } + + CPLUSPLUS_END_NAMESPACE |