blob: 39a16d2d3e8de52b40a7f6551f0b7987f6484b2c [file] [log] [blame]
Chris Lattnerb9093cd2006-08-04 04:39:53 +00001//===--- Parse.cpp - C Language Family Parser -----------------------------===//
Chris Lattner0bb5f832006-07-31 01:59:18 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner 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 Parser interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
Chris Lattnerb9093cd2006-08-04 04:39:53 +000015#include "clang/Parse/Declarations.h"
Chris Lattner971c6b62006-08-05 22:46:42 +000016#include "clang/Parse/Scope.h"
Chris Lattner0bb5f832006-07-31 01:59:18 +000017using namespace llvm;
18using namespace clang;
19
20Parser::Parser(Preprocessor &pp, ParserActions &actions)
Chris Lattner971c6b62006-08-05 22:46:42 +000021 : PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {
22 // Create the global scope, install it as the current scope.
23 CurScope = new Scope(0);
Chris Lattneracd58a32006-08-06 17:24:14 +000024 Tok.SetKind(tok::eof);
Chris Lattnereec40f92006-08-06 21:55:29 +000025
26 ParenCount = BracketCount = BraceCount = 0;
Chris Lattner971c6b62006-08-05 22:46:42 +000027}
28
29Parser::~Parser() {
30 delete CurScope;
31}
32
Chris Lattner0bb5f832006-07-31 01:59:18 +000033
Chris Lattnerb9093cd2006-08-04 04:39:53 +000034void Parser::Diag(SourceLocation Loc, unsigned DiagID,
Chris Lattner0bb5f832006-07-31 01:59:18 +000035 const std::string &Msg) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +000036 Diags.Report(Loc, DiagID, Msg);
Chris Lattner0bb5f832006-07-31 01:59:18 +000037}
38
Chris Lattner70f32b72006-07-31 05:09:04 +000039//===----------------------------------------------------------------------===//
Chris Lattnereec40f92006-08-06 21:55:29 +000040// Error recovery.
41//===----------------------------------------------------------------------===//
42
43/// SkipUntil - Read tokens until we get to the specified token, then consume
44/// it (unless DontConsume is false). Because we cannot guarantee that the
45/// token will ever occur, this skips to the next token, or to some likely
46/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
47/// character.
48///
49/// If SkipUntil finds the specified token, it returns true, otherwise it
50/// returns false.
51bool Parser::SkipUntil(tok::TokenKind T, bool StopAtSemi, bool DontConsume) {
52 while (1) {
53 // If we found the token, stop and return true.
54 if (Tok.getKind() == T) {
55 if (DontConsume) {
56 // Noop, don't consume the token.
57 } else if (isTokenParen()) {
58 ConsumeParen();
59 } else if (isTokenBracket()) {
60 ConsumeBracket();
61 } else if (isTokenBrace()) {
62 ConsumeBrace();
63 } else if (T == tok::string_literal) {
64 ConsumeStringToken();
65 } else {
66 ConsumeToken();
67 }
68 return true;
69 }
70
71 switch (Tok.getKind()) {
72 case tok::eof:
73 // Ran out of tokens.
74 return false;
75
76 case tok::l_paren:
77 // Recursively skip properly-nested parens.
78 ConsumeParen();
79 SkipUntil(tok::r_paren);
80 break;
81 case tok::l_square:
82 // Recursively skip properly-nested square brackets.
83 ConsumeBracket();
84 SkipUntil(tok::r_square);
85 break;
86 case tok::l_brace:
87 // Recursively skip properly-nested braces.
88 ConsumeBrace();
89 SkipUntil(tok::r_brace);
90 break;
91
92 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
93 // Since the user wasn't looking for this token (if they were, it would
94 // already be handled), this isn't balanced. If there is a LHS token at a
95 // higher level, we will assume that this matches the unbalanced token
96 // and return it. Otherwise, this is a spurious RHS token, which we skip.
97 case tok::r_paren:
98 if (ParenCount) return false; // Matches something.
99 ConsumeParen();
100 break;
101 case tok::r_square:
102 if (BracketCount) return false; // Matches something.
103 ConsumeBracket();
104 break;
105 case tok::r_brace:
106 if (BraceCount) return false; // Matches something.
107 ConsumeBrace();
108 break;
109
110 case tok::string_literal:
111 ConsumeStringToken();
112 break;
113 case tok::semi:
114 if (StopAtSemi)
115 return false;
116 // FALL THROUGH.
117 default:
118 // Skip this token.
119 ConsumeToken();
120 break;
121 }
122 }
123}
124
125//===----------------------------------------------------------------------===//
Chris Lattner70f32b72006-07-31 05:09:04 +0000126// C99 6.9: External Definitions.
127//===----------------------------------------------------------------------===//
Chris Lattner0bb5f832006-07-31 01:59:18 +0000128
129/// ParseTranslationUnit:
Chris Lattner70f32b72006-07-31 05:09:04 +0000130/// translation-unit: [C99 6.9]
Chris Lattner0bb5f832006-07-31 01:59:18 +0000131/// external-declaration
132/// translation-unit external-declaration
133void Parser::ParseTranslationUnit() {
134
135 if (Tok.getKind() == tok::eof) // Empty source file is an extension.
136 Diag(diag::ext_empty_source_file);
137
138 while (Tok.getKind() != tok::eof)
139 ParseExternalDeclaration();
140}
141
142/// ParseExternalDeclaration:
Chris Lattner70f32b72006-07-31 05:09:04 +0000143/// external-declaration: [C99 6.9]
Chris Lattner0bb5f832006-07-31 01:59:18 +0000144/// function-definition [TODO]
145/// declaration [TODO]
146/// [EXT] ';'
147/// [GNU] asm-definition [TODO]
148/// [GNU] __extension__ external-declaration [TODO]
149/// [OBJC] objc-class-definition [TODO]
150/// [OBJC] objc-class-declaration [TODO]
151/// [OBJC] objc-alias-declaration [TODO]
152/// [OBJC] objc-protocol-definition [TODO]
153/// [OBJC] objc-method-definition [TODO]
154/// [OBJC] @end [TODO]
155///
156void Parser::ParseExternalDeclaration() {
157 switch (Tok.getKind()) {
158 case tok::semi:
159 Diag(diag::ext_top_level_semi);
160 ConsumeToken();
161 break;
162 default:
163 // We can't tell whether this is a function-definition or declaration yet.
164 ParseDeclarationOrFunctionDefinition();
165 break;
166 }
167}
168
169/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
Chris Lattner70f32b72006-07-31 05:09:04 +0000170/// a declaration. We can't tell which we have until we read up to the
171/// compound-statement in function-definition.
Chris Lattner0bb5f832006-07-31 01:59:18 +0000172///
Chris Lattner70f32b72006-07-31 05:09:04 +0000173/// function-definition: [C99 6.9.1]
174/// declaration-specifiers[opt] declarator declaration-list[opt]
175/// compound-statement [TODO]
176/// declaration: [C99 6.7]
Chris Lattner0bb5f832006-07-31 01:59:18 +0000177/// declaration-specifiers init-declarator-list[opt] ';' [TODO]
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000178/// [!C99] init-declarator-list ';' [TODO]
Chris Lattner70f32b72006-07-31 05:09:04 +0000179/// [OMP] threadprivate-directive [TODO]
180///
181/// init-declarator-list: [C99 6.7]
182/// init-declarator
183/// init-declarator-list ',' init-declarator
184/// init-declarator: [C99 6.7]
185/// declarator
186/// declarator '=' initializer
187///
Chris Lattner0bb5f832006-07-31 01:59:18 +0000188void Parser::ParseDeclarationOrFunctionDefinition() {
Chris Lattner70f32b72006-07-31 05:09:04 +0000189 // Parse the common declaration-specifiers piece.
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000190 DeclSpec DS;
191 ParseDeclarationSpecifiers(DS);
Chris Lattnerd2864882006-08-05 08:09:44 +0000192
193 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
Chris Lattner53361ac2006-08-10 05:19:57 +0000194 // declaration-specifiers init-declarator-list[opt] ';'
Chris Lattnerd2864882006-08-05 08:09:44 +0000195 if (Tok.getKind() == tok::semi)
196 assert(0 && "Unimp!");
197
Chris Lattner70f32b72006-07-31 05:09:04 +0000198
Chris Lattnerfff824f2006-08-07 06:31:38 +0000199 // Parse the first declarator.
200 Declarator DeclaratorInfo(DS, Declarator::FileContext);
201 ParseDeclarator(DeclaratorInfo);
202 // Error parsing the declarator?
203 if (DeclaratorInfo.getIdentifier() == 0) {
204 // If so, skip until the semi-colon or a }.
205 SkipUntil(tok::r_brace, true);
206 if (Tok.getKind() == tok::semi)
207 ConsumeToken();
208 return;
209 }
Chris Lattner70f32b72006-07-31 05:09:04 +0000210
Chris Lattnerfff824f2006-08-07 06:31:38 +0000211 // If the declarator is the start of a function definition, handle it.
212 if (Tok.getKind() == tok::equal || // int X()= -> not a function def
213 Tok.getKind() == tok::comma || // int X(), -> not a function def
214 Tok.getKind() == tok::semi || // int X(); -> not a function def
215 Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
216 Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
217 // FALL THROUGH.
218 } else if (DeclaratorInfo.isInnermostFunctionType() &&
219 (Tok.getKind() == tok::l_brace || // int X() {}
220 isDeclarationSpecifier())) { // int X(f) int f; {}
221 ParseFunctionDefinition(DeclaratorInfo);
222 return;
223 } else {
224 if (DeclaratorInfo.isInnermostFunctionType())
225 Diag(Tok, diag::err_expected_fn_body);
226 else
227 Diag(Tok, diag::err_expected_after_declarator);
228 SkipUntil(tok::r_brace, true);
229 if (Tok.getKind() == tok::semi)
230 ConsumeToken();
231 return;
232 }
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000233
Chris Lattner53361ac2006-08-10 05:19:57 +0000234 // Parse the init-declarator-list for a normal declaration.
235 ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
Chris Lattner70f32b72006-07-31 05:09:04 +0000236}
237
Chris Lattnerfff824f2006-08-07 06:31:38 +0000238/// ParseFunctionDefinition - We parsed and verified that the specified
239/// Declarator is well formed. If this is a K&R-style function, read the
240/// parameters declaration-list, then start the compound-statement.
241///
242/// declaration-specifiers[opt] declarator declaration-list[opt]
243/// compound-statement [TODO]
244///
245void Parser::ParseFunctionDefinition(Declarator &D) {
246 const DeclaratorTypeInfo &FnTypeInfo = D.getTypeObject(0);
247 assert(FnTypeInfo.Kind == DeclaratorTypeInfo::Function &&
248 "This isn't a function declarator!");
249
250 // If this declaration was formed with a K&R-style identifier list for the
251 // arguments, parse declarations for all of the args next.
252 // int foo(a,b) int a; float b; {}
253 if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
254 // Read all the argument declarations.
Chris Lattner53361ac2006-08-10 05:19:57 +0000255 while (isDeclarationSpecifier())
256 ParseDeclaration(Declarator::KNRTypeListContext);
Chris Lattnerfff824f2006-08-07 06:31:38 +0000257
258 // Note, check that we got them all.
259 } else {
260 //if (isDeclarationSpecifier())
261 // Diag('k&r declspecs with prototype?');
262
263 // FIXME: Install the arguments into the current scope.
264 }
265
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000266 // We should have an opening brace now.
267 if (Tok.getKind() != tok::l_brace) {
268 Diag(Tok, diag::err_expected_fn_body);
269
270 // Skip over garbage, until we get to '{'. Don't eat the '{'.
271 SkipUntil(tok::l_brace, true, true);
272
273 // If we didn't find the '{', bail out.
274 if (Tok.getKind() != tok::l_brace)
275 return;
276 }
Chris Lattnerfff824f2006-08-07 06:31:38 +0000277
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000278 ParseCompoundStatement();
Chris Lattnerfff824f2006-08-07 06:31:38 +0000279}
280