blob: 9b74eea791f6056b2bee08c700c22f6ca3df53f3 [file] [log] [blame]
Chris Lattnerc951dae2006-08-10 04:23:57 +00001//===--- Expression.cpp - Expression Parsing ------------------------------===//
2//
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 Expression parsing implementation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Basic/Diagnostic.h"
16using namespace llvm;
17using namespace clang;
18
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000019// C99 6.7.8
20void Parser::ParseInitializer() {
21 // FIXME: STUB.
22 ParseAssignmentExpression();
23}
24
25
26
Chris Lattnerc951dae2006-08-10 04:23:57 +000027Parser::ExprTy Parser::ParseExpression() {
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000028 ParseCastExpression();
Chris Lattnerc951dae2006-08-10 04:23:57 +000029 return 0;
30}
31
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000032// Expr that doesn't include commas.
33void Parser::ParseAssignmentExpression() {
34 ParseExpression();
35}
36
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000037
38void Parser::ParseCastExpression() {
39 ParseUnaryExpression();
40}
41
42/// ParseUnaryExpression
43/// unary-expression: [C99 6.5.3]
44/// postfix-expression
45/// '++' unary-expression
46/// '--' unary-expression
47/// unary-operator cast-expression
48/// 'sizeof' unary-expression
49/// 'sizeof' '(' type-name ')'
50/// [GNU] '__alignof' unary-expression
51/// [GNU] '__alignof' '(' type-name ')'
52/// [GNU] '&&' identifier
53/// unary-operator: one of
54/// '&' '*' '+' '-' '~' '!'
55/// [GNU] '__extension__' '__real' '__imag'
56///
57void Parser::ParseUnaryExpression() {
58 switch (Tok.getKind()) {
59 default: // unary-expression: postfix-expression
60 ParsePostfixExpression();
61 break;
62 case tok::plusplus: // unary-expression: '++' unary-expression
63 case tok::minusminus: // unary-expression: '--' unary-expression
64 ConsumeToken();
65 ParseUnaryExpression();
66 break;
67 case tok::amp: // unary-expression: '&' cast-expression
68 case tok::star: // unary-expression: '*' cast-expression
69 case tok::plus: // unary-expression: '+' cast-expression
70 case tok::minus: // unary-expression: '-' cast-expression
71 case tok::tilde: // unary-expression: '~' cast-expression
72 case tok::exclaim: // unary-expression: '!' cast-expression
73 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
74 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
75 //case tok::kw__extension__: [TODO]
76 ConsumeToken();
77 ParseCastExpression();
78 break;
79
80 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
81 // unary-expression: 'sizeof' '(' type-name ')'
82 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
83 // unary-expression: '__alignof' '(' type-name ')'
84 ParseSizeofAlignofExpression();
85 break;
86 case tok::ampamp: // unary-expression: '&&' identifier
87 Diag(Tok, diag::ext_gnu_address_of_label);
88 ConsumeToken();
89 if (Tok.getKind() == tok::identifier) {
90 ConsumeToken();
91 } else {
92 Diag(Tok, diag::err_expected_ident);
93 ConsumeToken(); // FIXME: Should just return error!
94 return;
95 }
96 break;
97 }
98}
99
100/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
101/// unary-expression: [C99 6.5.3]
102/// 'sizeof' unary-expression
103/// 'sizeof' '(' type-name ')'
104/// [GNU] '__alignof' unary-expression
105/// [GNU] '__alignof' '(' type-name ')'
106void Parser::ParseSizeofAlignofExpression() {
107 assert((Tok.getKind() == tok::kw_sizeof ||
108 Tok.getKind() == tok::kw___alignof) &&
109 "Not a sizeof/alignof expression!");
110 ConsumeToken();
111
112 // If the operand doesn't start with an '(', it must be an expression.
113 if (Tok.getKind() != tok::l_paren) {
114 ParseUnaryExpression();
115 return;
116 }
117
118 // If it starts with a '(', we know that it is either a parenthesized
119 // type-name, or it is a unary-expression that starts with a compound literal,
120 // or starts with a primary-expression that is a parenthesized expression.
121 SourceLocation LParenLoc = Tok.getLocation();
122 ConsumeParen();
123
124 if (isTypeSpecifierQualifier()) {
125 // This is now known to be either a parenthesized type-name, or a compound
126 // literal.
127
128
129 // FIXME: ParseTypeName.
130 assert(0 && "implement!");
131 } else {
132 // Otherwise, this is known to be a parenthesized-expression. Parse the
133 // rest of the parethesized-expression here.
134 ParseExpression();
135
136 }
137
138 if (Tok.getKind() == tok::r_paren) {
139 ConsumeParen();
140 } else {
141 Diag(Tok, diag::err_expected_rparen);
142 Diag(LParenLoc, diag::err_matching, "(");
143 SkipUntil(tok::r_paren);
144 }
145}
146
Chris Lattner52a99e52006-08-10 20:56:00 +0000147/// ParsePostfixExpression
148/// postfix-expression: [C99 6.5.2]
149/// primary-expression
150/// postfix-expression '[' expression ']'
151/// postfix-expression '(' argument-expression-list[opt] ')'
152/// postfix-expression '.' identifier
153/// postfix-expression '->' identifier
154/// postfix-expression '++'
155/// postfix-expression '--'
156/// '(' type-name ')' '{' initializer-list '}'
157/// '(' type-name ')' '{' initializer-list ',' '}'
158///
159/// argument-expression-list: [C99 6.5.2]
160/// argument-expression
161/// argument-expression-list ',' argument-expression
162///
163/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000164/// identifier
165/// constant
166/// string-literal
167/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +0000168/// '__func__' [C99 6.4.2.2]
169/// [GNU] '__FUNCTION__'
170/// [GNU] '__PRETTY_FUNCTION__'
171/// [GNU] '(' compound-statement ')'
172/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
173/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
174/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
175/// assign-expr ')'
176/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
177/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
178/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
179/// [OBC] '@protocol' '(' identifier ')' [TODO]
180/// [OBC] '@encode' '(' type-name ')' [TODO]
181/// [OBC] objc-string-literal [TODO]
182///
183/// constant: [C99 6.4.4]
184/// integer-constant
185/// floating-constant
186/// enumeration-constant -> identifier
187/// character-constant
188///
189/// [GNU] offsetof-member-designator:
190/// [GNU] identifier
191/// [GNU] offsetof-member-designator '.' identifier
192/// [GNU] offsetof-member-designator '[' expression ']'
193///
194void Parser::ParsePostfixExpression() {
195 // First step, parse the primary expression.
196 switch (Tok.getKind()) {
197 // primary-expression
198 case tok::identifier: // primary-expression: identifier
199 // constant: enumeration-constant
200 case tok::numeric_constant: // constant: integer-constant
201 // constant: floating-constant
202 case tok::char_constant: // constant: character-constant
203 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
204 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
205 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
206 ConsumeToken();
207 break;
208 case tok::string_literal: // primary-expression: string-literal
209 ParseStringLiteralExpression();
210 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000211 case tok::l_paren: // primary-expression: '(' expression ')'
212 // primary-expression: '(' compound-statement ')'
213 ParseParenExpression(false/*allow statement exprs, initializers */);
Chris Lattner52a99e52006-08-10 20:56:00 +0000214 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000215 case tok::kw___builtin_va_arg:
216 case tok::kw___builtin_offsetof:
217 case tok::kw___builtin_choose_expr:
218 case tok::kw___builtin_types_compatible_p:
219 assert(0 && "FIXME: UNIMP!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000220 default:
221 Diag(Tok, diag::err_expected_expression);
Chris Lattnerf8339772006-08-10 22:01:51 +0000222 // Guarantee forward progress.
223 // FIXME: this dies on 'if ({1; });'. Expression parsing should return a
224 // bool for failure. This will cause higher-level parsing stuff to do the
225 // right thing.
226 ConsumeToken();
Chris Lattner52a99e52006-08-10 20:56:00 +0000227 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000228 }
229
230 // Now that the primary-expression piece of the postfix-expression has been
231 // parsed, see if there are any postfix-expression pieces here.
232 SourceLocation Loc;
233 while (1) {
234 switch (Tok.getKind()) {
235 default:
236 return;
237 case tok::l_square: // postfix-expression: p-e '[' expression ']'
238 Loc = Tok.getLocation();
239 ConsumeBracket();
240 ParseExpression();
241 if (Tok.getKind() == tok::r_square) {
242 ConsumeBracket();
243 } else {
244 Diag(Tok, diag::err_expected_rsquare);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000245 Diag(Loc, diag::err_matching, "[");
Chris Lattnerf8339772006-08-10 22:01:51 +0000246 SkipUntil(tok::r_square);
247 }
248 break;
249
250 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
251 Loc = Tok.getLocation();
252 ConsumeParen();
253
254 while (1) {
255 // FIXME: This should be argument-expression!
256 ParseAssignmentExpression();
257
258 if (Tok.getKind() != tok::comma)
259 break;
260 ConsumeToken(); // Next argument.
261 }
262
263 if (Tok.getKind() == tok::r_paren) {
264 ConsumeParen();
265 } else {
266 Diag(Tok, diag::err_expected_rparen);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000267 Diag(Loc, diag::err_matching, "(");
Chris Lattnerf8339772006-08-10 22:01:51 +0000268 SkipUntil(tok::r_paren);
269 }
270 break;
271
272 case tok::arrow: // postfix-expression: p-e '->' identifier
273 case tok::period: // postfix-expression: p-e '.' identifier
274 ConsumeToken();
275 if (Tok.getKind() != tok::identifier) {
276 Diag(Tok, diag::err_expected_ident);
277 return;
278 }
279 ConsumeToken();
280 break;
281
282 case tok::plusplus: // postfix-expression: postfix-expression '++'
283 case tok::minusminus: // postfix-expression: postfix-expression '--'
284 ConsumeToken();
285 break;
286 }
287 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000288}
289
290/// ParseStringLiteralExpression - This handles the various token types that
291/// form string literals, and also handles string concatenation [C99 5.1.1.2,
292/// translation phase #6].
293///
294/// primary-expression: [C99 6.5.1]
295/// string-literal
296void Parser::ParseStringLiteralExpression() {
297 assert(isStringLiteral() && "Not a string literal!");
298 ConsumeStringToken();
299
300 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
301 // considered to be strings.
302 while (isStringLiteral())
303 ConsumeStringToken();
304}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000305
Chris Lattnerc951dae2006-08-10 04:23:57 +0000306
Chris Lattnerf8339772006-08-10 22:01:51 +0000307/// ParseParenExpression - C99 6.5.1p5
Chris Lattnerc951dae2006-08-10 04:23:57 +0000308/// primary-expression:
309/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000310/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
311/// postfix-expression: [C99 6.5.2]
312/// '(' type-name ')' '{' initializer-list '}'
313/// '(' type-name ')' '{' initializer-list ',' '}'
314///
315void Parser::ParseParenExpression(bool ParenExprOnly) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000316 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
317 SourceLocation OpenLoc = Tok.getLocation();
318 ConsumeParen();
319
Chris Lattnerf8339772006-08-10 22:01:51 +0000320 if (!ParenExprOnly && Tok.getKind() == tok::l_brace &&
321 !getLang().NoExtensions) {
322 Diag(Tok, diag::ext_gnu_statement_expr);
323 ParseCompoundStatement();
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000324 } else if (!ParenExprOnly && isTypeSpecifierQualifier()) {
Chris Lattnerf8339772006-08-10 22:01:51 +0000325 // FIXME: Implement compound literals: C99 6.5.2.5. Type-name: C99 6.7.6.
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000326 assert(0 && "IMPLEMENT THIS!");
Chris Lattnerf8339772006-08-10 22:01:51 +0000327 } else {
328 ParseExpression();
329 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000330
331 if (Tok.getKind() == tok::r_paren) {
332 ConsumeParen();
333 } else {
334 Diag(Tok, diag::err_expected_rparen);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000335 Diag(OpenLoc, diag::err_matching, "(");
Chris Lattnerc951dae2006-08-10 04:23:57 +0000336 }
337}