blob: ca0003440fe04f90df7a317570d80558b8c402dc [file] [log] [blame]
Argiris Kirtzidis9d784332008-06-24 22:12:16 +00001//===--- ParseCXXInlineMethods.cpp - C++ class inline methods parsing------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements parsing for C++ class inline methods.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Parse/DeclSpec.h"
16#include "clang/Parse/Scope.h"
17using namespace clang;
18
19/// ParseInlineCXXMethodDef - We parsed and verified that the specified
20/// Declarator is a well formed C++ inline method definition. Now lex its body
21/// and store its tokens for parsing after the C++ class is complete.
22Parser::DeclTy *
23Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
24 assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
25 "This isn't a function declarator!");
Argiris Kirtzidis0fb15bf2008-06-24 22:31:41 +000026 assert(Tok.is(tok::l_brace) && "Current token not a '{'!");
Argiris Kirtzidis9d784332008-06-24 22:12:16 +000027
28 DeclTy *FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0, 0);
29
Argiris Kirtzidis9d784332008-06-24 22:12:16 +000030 // Consume the tokens and store them for later parsing.
31
32 getCurTopClassStack().push(LexedMethod(FnD));
33 TokensTy &Toks = getCurTopClassStack().top().Toks;
34
35 // Begin by storing the '{' token.
36 Toks.push_back(Tok);
37 ConsumeBrace();
38 ConsumeAndStoreUntil(tok::r_brace, Toks);
39
40 return FnD;
41}
42
43/// ParseLexedMethodDefs - We finished parsing the member specification of a top
44/// (non-nested) C++ class. Now go over the stack of lexed methods that were
45/// collected during its parsing and parse them all.
46void Parser::ParseLexedMethodDefs() {
47 while (!getCurTopClassStack().empty()) {
48 LexedMethod &LM = getCurTopClassStack().top();
49
50 assert(!LM.Toks.empty() && "Empty body!");
51 // Append the current token at the end of the new token stream so that it
52 // doesn't get lost.
53 LM.Toks.push_back(Tok);
54 PP.EnterTokenStream(&LM.Toks.front(), LM.Toks.size(), true, false);
55
56 // Consume the previously pushed token.
57 ConsumeAnyToken();
58 assert(Tok.is(tok::l_brace) && "Inline method not starting with '{'");
59
60 // Parse the method body. Function body parsing code is similar enough
61 // to be re-used for method bodies as well.
62 EnterScope(Scope::FnScope|Scope::DeclScope);
63 Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
64
65 ParseFunctionStatementBody(LM.D, Tok.getLocation(), Tok.getLocation());
66
67 getCurTopClassStack().pop();
68 }
69}
70
71/// ConsumeAndStoreUntil - Consume and store the token at the passed token
72/// container until the token 'T' is reached (which gets consumed/stored too).
73/// Returns true if token 'T' was found.
74/// NOTE: This is a specialized version of Parser::SkipUntil.
75bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks) {
76 // We always want this function to consume at least one token if the first
77 // token isn't T and if not at EOF.
78 bool isFirstTokenConsumed = true;
79 while (1) {
80 // If we found one of the tokens, stop and return true.
81 if (Tok.is(T)) {
82 Toks.push_back(Tok);
83 ConsumeAnyToken();
84 return true;
85 }
86
87 switch (Tok.getKind()) {
88 case tok::eof:
89 // Ran out of tokens.
90 return false;
91
92 case tok::l_paren:
93 // Recursively consume properly-nested parens.
94 Toks.push_back(Tok);
95 ConsumeParen();
96 ConsumeAndStoreUntil(tok::r_paren, Toks);
97 break;
98 case tok::l_square:
99 // Recursively consume properly-nested square brackets.
100 Toks.push_back(Tok);
101 ConsumeBracket();
102 ConsumeAndStoreUntil(tok::r_square, Toks);
103 break;
104 case tok::l_brace:
105 // Recursively consume properly-nested braces.
106 Toks.push_back(Tok);
107 ConsumeBrace();
108 ConsumeAndStoreUntil(tok::r_brace, Toks);
109 break;
110
111 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
112 // Since the user wasn't looking for this token (if they were, it would
113 // already be handled), this isn't balanced. If there is a LHS token at a
114 // higher level, we will assume that this matches the unbalanced token
115 // and return it. Otherwise, this is a spurious RHS token, which we skip.
116 case tok::r_paren:
117 if (ParenCount && !isFirstTokenConsumed)
118 return false; // Matches something.
119 Toks.push_back(Tok);
120 ConsumeParen();
121 break;
122 case tok::r_square:
123 if (BracketCount && !isFirstTokenConsumed)
124 return false; // Matches something.
125 Toks.push_back(Tok);
126 ConsumeBracket();
127 break;
128 case tok::r_brace:
129 if (BraceCount && !isFirstTokenConsumed)
130 return false; // Matches something.
131 Toks.push_back(Tok);
132 ConsumeBrace();
133 break;
134
135 case tok::string_literal:
136 case tok::wide_string_literal:
137 Toks.push_back(Tok);
138 ConsumeStringToken();
139 break;
140 default:
141 // consume this token.
142 Toks.push_back(Tok);
143 ConsumeToken();
144 break;
145 }
146 isFirstTokenConsumed = false;
147 }
148}