blob: e093f19c2c92686d5ce784ec5daa3f45ce0c972b [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- ParseObjc.cpp - Objective C Parsing ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Steve Naroff and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Objective-C portions of the Parser interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Basic/Diagnostic.h"
16#include "llvm/ADT/SmallVector.h"
17using namespace clang;
18
19
20/// ParseExternalDeclaration:
21/// external-declaration: [C99 6.9]
22/// [OBJC] objc-class-definition
23/// [OBJC] objc-class-declaration [TODO]
24/// [OBJC] objc-alias-declaration [TODO]
25/// [OBJC] objc-protocol-definition [TODO]
26/// [OBJC] objc-method-definition [TODO]
27/// [OBJC] '@' 'end' [TODO]
Steve Narofffb367882007-08-20 21:31:48 +000028Parser::DeclTy *Parser::ParseObjCAtDirectives() {
Chris Lattner4b009652007-07-25 00:24:17 +000029 SourceLocation AtLoc = ConsumeToken(); // the "@"
30
31 IdentifierInfo *II = Tok.getIdentifierInfo();
32 switch (II ? II->getObjCKeywordID() : tok::objc_not_keyword) {
33 case tok::objc_class:
34 return ParseObjCAtClassDeclaration(AtLoc);
35 case tok::objc_interface:
Steve Narofffb367882007-08-20 21:31:48 +000036 return ParseObjCAtInterfaceDeclaration(AtLoc);
Chris Lattner4b009652007-07-25 00:24:17 +000037 case tok::objc_protocol:
38 return ParseObjCAtProtocolDeclaration();
39 case tok::objc_implementation:
40 return ParseObjCAtImplementationDeclaration();
41 case tok::objc_end:
42 return ParseObjCAtEndDeclaration();
43 case tok::objc_compatibility_alias:
44 return ParseObjCAtAliasDeclaration();
45 default:
46 Diag(AtLoc, diag::err_unexpected_at);
47 SkipUntil(tok::semi);
Steve Narofffb367882007-08-20 21:31:48 +000048 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000049 }
50}
51
52///
53/// objc-class-declaration:
54/// '@' 'class' identifier-list ';'
55///
Steve Narofffb367882007-08-20 21:31:48 +000056Parser::DeclTy *Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
Chris Lattner4b009652007-07-25 00:24:17 +000057 ConsumeToken(); // the identifier "class"
58 llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
59
60 while (1) {
61 if (Tok.getKind() != tok::identifier) {
62 Diag(Tok, diag::err_expected_ident);
63 SkipUntil(tok::semi);
Steve Narofffb367882007-08-20 21:31:48 +000064 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000065 }
66
67 ClassNames.push_back(Tok.getIdentifierInfo());
68 ConsumeToken();
69
70 if (Tok.getKind() != tok::comma)
71 break;
72
73 ConsumeToken();
74 }
75
76 // Consume the ';'.
77 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
Steve Narofffb367882007-08-20 21:31:48 +000078 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +000079
Steve Narofffb367882007-08-20 21:31:48 +000080 return Actions.ParsedObjcClassDeclaration(CurScope,
81 &ClassNames[0], ClassNames.size());
Chris Lattner4b009652007-07-25 00:24:17 +000082}
83
Steve Narofffb367882007-08-20 21:31:48 +000084///
85/// objc-interface:
86/// objc-class-interface-attributes[opt] objc-class-interface
87/// objc-category-interface
88///
89/// objc-class-interface:
90/// '@' 'interface' identifier objc-superclass[opt]
91/// objc-protocol-refs[opt]
92/// objc-class-instance-variables[opt]
93/// objc-interface-decl-list
94/// @end
95///
96/// objc-category-interface:
97/// '@' 'interface' identifier '(' identifier[opt] ')'
98/// objc-protocol-refs[opt]
99/// objc-interface-decl-list
100/// @end
101///
102/// objc-superclass:
103/// ':' identifier
104///
105/// objc-class-interface-attributes:
106/// __attribute__((visibility("default")))
107/// __attribute__((visibility("hidden")))
108/// __attribute__((deprecated))
109/// __attribute__((unavailable))
110/// __attribute__((objc_exception)) - used by NSException on 64-bit
111///
112Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
113 SourceLocation atLoc, AttributeList *attrList) {
114 assert(Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface &&
115 "ParseObjCAtInterfaceDeclaration(): Expected @interface");
116 ConsumeToken(); // the "interface" identifier
117
118 if (Tok.getKind() != tok::identifier) {
119 Diag(Tok, diag::err_expected_ident); // missing class or category name.
120 return 0;
121 }
122 // We have a class or category name - consume it.
123 IdentifierInfo *nameId = Tok.getIdentifierInfo();
124 SourceLocation nameLoc = ConsumeToken();
125
126 if (Tok.getKind() == tok::l_paren) { // we have a category
127 SourceLocation lparenLoc = ConsumeParen();
128 SourceLocation categoryLoc, rparenLoc;
129 IdentifierInfo *categoryId = 0;
130
131 // OBJC2: The cateogry name is optional (not an error).
132 if (Tok.getKind() == tok::identifier) {
133 categoryId = Tok.getIdentifierInfo();
134 categoryLoc = ConsumeToken();
135 }
136 if (Tok.getKind() != tok::r_paren) {
137 Diag(Tok, diag::err_expected_rparen);
138 SkipUntil(tok::r_paren, false); // don't stop at ';'
139 return 0;
140 }
141 rparenLoc = ConsumeParen();
142 // Next, we need to check for any protocol references.
143 if (Tok.getKind() == tok::less) {
144 if (ParseObjCProtocolReferences())
145 return 0;
146 }
147 if (attrList) // categories don't support attributes.
148 Diag(Tok, diag::err_objc_no_attributes_on_category);
149
150 //ParseObjCInterfaceDeclList();
151
152 if (Tok.getKind() != tok::at) { // check for @end
153 Diag(Tok, diag::err_objc_missing_end);
154 return 0;
155 }
156 SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
157 if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
158 Diag(Tok, diag::err_objc_missing_end);
159 return 0;
160 }
161 ConsumeToken(); // the "end" identifier
162 return 0;
163 }
164 // Parse a class interface.
165 IdentifierInfo *superClassId = 0;
166 SourceLocation superClassLoc;
167
168 if (Tok.getKind() == tok::colon) { // a super class is specified.
169 ConsumeToken();
170 if (Tok.getKind() != tok::identifier) {
171 Diag(Tok, diag::err_expected_ident); // missing super class name.
172 return 0;
173 }
174 superClassId = Tok.getIdentifierInfo();
175 superClassLoc = ConsumeToken();
176 }
177 // Next, we need to check for any protocol references.
178 if (Tok.getKind() == tok::less) {
179 if (ParseObjCProtocolReferences())
180 return 0;
181 }
182 if (Tok.getKind() == tok::l_brace)
183 ParseObjCClassInstanceVariables();
184
185 //ParseObjCInterfaceDeclList();
186
187 if (Tok.getKind() != tok::at) { // check for @end
188 Diag(Tok, diag::err_objc_missing_end);
189 return 0;
190 }
191 SourceLocation atEndLoc = ConsumeToken(); // eat the @ sign
192 if (Tok.getIdentifierInfo()->getObjCKeywordID() != tok::objc_end) {
193 Diag(Tok, diag::err_objc_missing_end);
194 return 0;
195 }
196 ConsumeToken(); // the "end" identifier
197 return 0;
198}
199
200/// objc-interface-decl-list:
201/// empty
202/// objc-interface-decl-list objc-method-proto
203/// objc-interface-decl-list objc-property-decl [OBJC2]
204/// objc-interface-decl-list declaration
205/// objc-interface-decl-list ';'
206///
207void Parser::ParseObjCInterfaceDeclList() {
Chris Lattner4b009652007-07-25 00:24:17 +0000208 assert(0 && "Unimp");
209}
Steve Narofffb367882007-08-20 21:31:48 +0000210
211/// objc-protocol-refs:
212/// '<' identifier-list '>'
213///
214bool Parser::ParseObjCProtocolReferences() {
215 assert(Tok.getKind() == tok::less && "expected <");
216
217 ConsumeToken(); // the "<"
218 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
219
220 while (1) {
221 if (Tok.getKind() != tok::identifier) {
222 Diag(Tok, diag::err_expected_ident);
223 SkipUntil(tok::greater);
224 return true;
225 }
226 ProtocolRefs.push_back(Tok.getIdentifierInfo());
227 ConsumeToken();
228
229 if (Tok.getKind() != tok::comma)
230 break;
231 ConsumeToken();
232 }
233 // Consume the '>'.
234 return ExpectAndConsume(tok::greater, diag::err_expected_greater);
235}
236
237/// objc-class-instance-variables:
238/// '{' objc-instance-variable-decl-list[opt] '}'
239///
240/// objc-instance-variable-decl-list:
241/// objc-visibility-spec
242/// objc-instance-variable-decl ';'
243/// ';'
244/// objc-instance-variable-decl-list objc-visibility-spec
245/// objc-instance-variable-decl-list objc-instance-variable-decl ';'
246/// objc-instance-variable-decl-list ';'
247///
248/// objc-visibility-spec:
249/// @private
250/// @protected
251/// @public
252///
253/// objc-instance-variable-decl:
254/// struct-declaration
255///
256void Parser::ParseObjCClassInstanceVariables() {
Chris Lattner4b009652007-07-25 00:24:17 +0000257 assert(0 && "Unimp");
258}
Steve Narofffb367882007-08-20 21:31:48 +0000259
260/// objc-protocol-declaration:
261/// objc-protocol-definition
262/// objc-protocol-forward-reference
263///
264/// objc-protocol-definition:
265/// @protocol identifier
266/// objc-protocol-refs[opt]
267/// objc-methodprotolist
268/// @end
269///
270/// objc-protocol-forward-reference:
271/// @protocol identifier-list ';'
272///
273/// "@protocol identifier ;" should be resolved as "@protocol
274/// identifier-list ;": objc-methodprotolist may not start with a
275/// semicolon in the first alternative if objc-protocol-refs are omitted.
276
277Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000278 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000279 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000280}
Steve Narofffb367882007-08-20 21:31:48 +0000281
282/// objc-implementation:
283/// objc-class-implementation-prologue
284/// objc-category-implementation-prologue
285///
286/// objc-class-implementation-prologue:
287/// @implementation identifier objc-superclass[opt]
288/// objc-class-instance-variables[opt]
289///
290/// objc-category-implementation-prologue:
291/// @implementation identifier ( identifier )
292
293Parser::DeclTy *Parser::ParseObjCAtImplementationDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000294 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000295 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000296}
Steve Narofffb367882007-08-20 21:31:48 +0000297Parser::DeclTy *Parser::ParseObjCAtEndDeclaration() {
Chris Lattner4b009652007-07-25 00:24:17 +0000298 assert(0 && "Unimp");
Steve Narofffb367882007-08-20 21:31:48 +0000299 return 0;
300}
301Parser::DeclTy *Parser::ParseObjCAtAliasDeclaration() {
302 assert(0 && "Unimp");
303 return 0;
Chris Lattner4b009652007-07-25 00:24:17 +0000304}
305
306void Parser::ParseObjCInstanceMethodDeclaration() {
307 assert(0 && "Unimp");
308}
309
310void Parser::ParseObjCClassMethodDeclaration() {
311 assert(0 && "Unimp");
312}
Anders Carlssona66cad42007-08-21 17:43:55 +0000313
314Parser::ExprResult Parser::ParseObjCExpression() {
315 SourceLocation AtLoc = ConsumeToken(); // the "@"
316
317 switch (Tok.getKind()) {
318 case tok::string_literal: // primary-expression: string-literal
319 case tok::wide_string_literal:
320 return ParseObjCStringLiteral();
321 default:
322 Diag(AtLoc, diag::err_unexpected_at);
323 SkipUntil(tok::semi);
324 break;
325 }
326
327 return 0;
328}
329
330Parser::ExprResult Parser::ParseObjCStringLiteral() {
331 ExprResult Res = ParseStringLiteralExpression();
332
333 if (Res.isInvalid) return Res;
334
335 return Actions.ParseObjCStringLiteral(Res.Val);
336}