Patch to parse @implementation prologue, method definitions,

objc2's @synthesize and @dynamic.

llvm-svn: 41667
This commit is contained in:
Fariborz Jahanian 2007-09-01 00:26:16 +00:00
parent dc9f36e6c4
commit 53cacaec46
3 changed files with 168 additions and 19 deletions

View File

@ -37,11 +37,15 @@ Parser::DeclTy *Parser::ParseObjCAtDirectives() {
case tok::objc_protocol:
return ParseObjCAtProtocolDeclaration(AtLoc);
case tok::objc_implementation:
return ParseObjCAtImplementationDeclaration();
return ParseObjCAtImplementationDeclaration(AtLoc);
case tok::objc_end:
return ParseObjCAtEndDeclaration();
return ParseObjCAtEndDeclaration(AtLoc);
case tok::objc_compatibility_alias:
return ParseObjCAtAliasDeclaration();
case tok::objc_synthesize:
return ParseObjCPropertySynthesize(AtLoc);
case tok::objc_dynamic:
return ParseObjCPropertyDynamic(AtLoc);
default:
Diag(AtLoc, diag::err_unexpected_at);
SkipUntil(tok::semi);
@ -232,7 +236,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl) {
}
}
if (Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) {
ParseObjCMethodPrototype();
ParseObjCMethodPrototype(true);
continue;
}
if (Tok.getKind() == tok::semi)
@ -339,8 +343,9 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
}
/// objc-methodproto:
/// objc-instance-method objc-method-decl objc-method-attributes[opt] ';'
/// objc-class-method objc-method-decl objc-method-attributes[opt] ';'
/// objc-instance-method objc-method-decl objc-method-attributes[opt]
/// ';'[opt]
/// objc-class-method objc-method-decl objc-method-attributes[opt] ';'[opt]
///
/// objc-instance-method: '-'
/// objc-class-method: '+'
@ -348,7 +353,7 @@ void Parser::ParseObjCPropertyDecl(DeclTy *interfaceDecl) {
/// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated))
///
void Parser::ParseObjCMethodPrototype() {
void Parser::ParseObjCMethodPrototype(bool decl) {
assert((Tok.getKind() == tok::minus || Tok.getKind() == tok::plus) &&
"expected +/-");
@ -362,8 +367,9 @@ void Parser::ParseObjCMethodPrototype() {
if (getLang().ObjC2 && Tok.getKind() == tok::kw___attribute)
ParseAttributes();
// Consume the ';'.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
if (decl)
// Consume the ';'.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "method proto");
}
/// objc-selector:
@ -700,12 +706,60 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc) {
/// objc-category-implementation-prologue:
/// @implementation identifier ( identifier )
Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration() {
assert(0 && "Unimp");
Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration(
SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
ConsumeToken(); // the "implementation" identifier
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident); // missing class or category name.
return 0;
}
// We have a class or category name - consume it.
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
if (Tok.getKind() == tok::l_paren) {
// we have a category implementation.
SourceLocation lparenLoc = ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
if (Tok.getKind() == tok::identifier) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
} else {
Diag(Tok, diag::err_expected_ident); // missing category name.
return 0;
}
if (Tok.getKind() != tok::r_paren) {
Diag(Tok, diag::err_expected_rparen);
SkipUntil(tok::r_paren, false); // don't stop at ';'
return 0;
}
rparenLoc = ConsumeParen();
return 0;
}
// We have a class implementation
if (Tok.getKind() == tok::colon) {
// We have a super class
ConsumeToken();
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident); // missing super class name.
return 0;
}
ConsumeToken(); // Consume super class name
}
if (Tok.getKind() == tok::l_brace)
ParseObjCClassInstanceVariables(0/*FIXME*/); // we have ivars
return 0;
}
Parser::DeclTy *Parser::ParseObjCAtEndDeclaration() {
assert(0 && "Unimp");
Parser::DeclTy *Parser::ParseObjCAtEndDeclaration(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_end) &&
"ParseObjCAtEndDeclaration(): Expected @end");
ConsumeToken(); // the "end" identifier
return 0;
}
Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
@ -713,12 +767,104 @@ Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
return 0;
}
void Parser::ParseObjCInstanceMethodDefinition() {
assert(0 && "Parser::ParseObjCInstanceMethodDefinition():: Unimp");
/// property-synthesis:
/// @synthesize property-ivar-list ';'
///
/// property-ivar-list:
/// property-ivar
/// property-ivar-list ',' property-ivar
///
/// property-ivar:
/// identifier
/// identifier '=' identifier
///
Parser::DeclTy *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
"ParseObjCPropertyDynamic(): Expected '@synthesize'");
SourceLocation loc = ConsumeToken(); // consume dynamic
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
return 0;
}
while (Tok.getKind() == tok::identifier) {
ConsumeToken(); // consume property name
if (Tok.getKind() == tok::equal) {
// property '=' ivar-name
ConsumeToken(); // consume '='
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
break;
}
ConsumeToken(); // consume ivar-name
}
if (Tok.getKind() != tok::comma)
break;
ConsumeToken(); // consume ','
}
if (Tok.getKind() != tok::semi)
Diag(Tok, diag::err_expected_semi_after, "@synthesize");
return 0;
}
/// property-dynamic:
/// @dynamic property-list
///
/// property-list:
/// identifier
/// property-list ',' identifier
///
Parser::DeclTy *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
"ParseObjCPropertyDynamic(): Expected '@dynamic'");
SourceLocation loc = ConsumeToken(); // consume dynamic
if (Tok.getKind() != tok::identifier) {
Diag(Tok, diag::err_expected_ident);
return 0;
}
while (Tok.getKind() == tok::identifier) {
ConsumeToken(); // consume property name
if (Tok.getKind() != tok::comma)
break;
ConsumeToken(); // consume ','
}
if (Tok.getKind() != tok::semi)
Diag(Tok, diag::err_expected_semi_after, "@dynamic");
return 0;
}
/// objc-method-def: objc-methodproto ';'[opt] '{' body '}'
///
void Parser::ParseObjCInstanceMethodDefinition() {
assert(Tok.getKind() == tok::minus &&
"ParseObjCInstanceMethodDefinition(): Expected '-'");
ParseObjCMethodPrototype(false);
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();
if (Tok.getKind() != tok::l_brace) {
Diag (Tok, diag::err_expected_lbrace);
return;
}
StmtResult FnBody = ParseCompoundStatementBody();
}
/// objc-method-def: objc-methodproto ';'[opt] '{' body '}'
///
void Parser::ParseObjCClassMethodDefinition() {
assert(0 && "Parser::ParseObjCClassMethodDefinition():: Unimp");
assert(Tok.getKind() == tok::plus &&
"ParseObjCClassMethodDefinition(): Expected '+'");
ParseObjCMethodPrototype(false);
// parse optional ';'
if (Tok.getKind() == tok::semi)
ConsumeToken();
if (Tok.getKind() != tok::l_brace) {
Diag (Tok, diag::err_expected_lbrace);
return;
}
StmtResult FnBody = ParseCompoundStatementBody();
}
Parser::ExprResult Parser::ParseObjCExpression() {

View File

@ -347,11 +347,12 @@ OBJC1_AT_KEYWORD(catch)
OBJC1_AT_KEYWORD(finally)
OBJC1_AT_KEYWORD(synchronized)
// I'm guessing this is an objc2 keyword, what are the others?
OBJC2_AT_KEYWORD(property)
OBJC2_AT_KEYWORD(package)
OBJC2_AT_KEYWORD(required)
OBJC2_AT_KEYWORD(optional)
OBJC2_AT_KEYWORD(synthesize)
OBJC2_AT_KEYWORD(dynamic)
// TODO: What to do about context-sensitive keywords like:
// bycopy/byref/in/inout/oneway/out?

View File

@ -262,9 +262,11 @@ private:
bool ParseObjCProtocolReferences();
void ParseObjCInterfaceDeclList(DeclTy *interfaceDecl);
DeclTy *ParseObjCAtProtocolDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtImplementationDeclaration();
DeclTy *ParseObjCAtEndDeclaration();
DeclTy *ParseObjCAtImplementationDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtEndDeclaration(SourceLocation atLoc);
DeclTy *ParseObjCAtAliasDeclaration();
DeclTy *ParseObjCPropertySynthesize(SourceLocation atLoc);
DeclTy *ParseObjCPropertyDynamic(SourceLocation atLoc);
IdentifierInfo *ParseObjCSelector();
// Definitions for Objective-c context sensitive keywords recognition.
@ -284,7 +286,7 @@ private:
void ParseObjCTypeName();
void ParseObjCMethodRequirement();
void ParseObjCMethodPrototype();
void ParseObjCMethodPrototype(bool decl);
void ParseObjCMethodDecl(tok::TokenKind mType, SourceLocation mLoc);
void ParseObjCPropertyAttribute(DeclTy *interfaceDecl);
void ParseObjCPropertyDecl(DeclTy *interfaceDecl);