blob: a8ecd0b3ff0dc15ee86038686362e413456853b4 [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.
Chris Lattnerf5fbd792006-08-10 23:56:11 +000022 if (Tok.getKind() == tok::l_brace) {
23 ConsumeBrace();
24 // FIXME: initializer-list
25 // Match the '}'.
26 MatchRHSPunctuation(tok::r_brace, Tok.getLocation(), "{",
27 diag::err_expected_rbrace);
28 return;
29 }
30
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000031 ParseAssignmentExpression();
32}
33
34
35
Chris Lattnerc951dae2006-08-10 04:23:57 +000036Parser::ExprTy Parser::ParseExpression() {
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000037 ParseCastExpression();
Chris Lattnerc951dae2006-08-10 04:23:57 +000038 return 0;
39}
40
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000041// Expr that doesn't include commas.
42void Parser::ParseAssignmentExpression() {
43 ParseExpression();
44}
45
Chris Lattner4564bc12006-08-10 23:14:52 +000046/// ParseCastExpression
47/// cast-expression: [C99 6.5.4]
48/// unary-expression
49/// '(' type-name ')' cast-expression
50///
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000051void Parser::ParseCastExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +000052 // If this doesn't start with an '(', then it is a unary-expression.
53 if (Tok.getKind() != tok::l_paren)
54 return ParseUnaryExpression();
55
Chris Lattner4add4e62006-08-11 01:33:00 +000056 ParenParseOption ParenExprType = CompoundLiteral;
57 ParseParenExpression(ParenExprType);
58
59 switch (ParenExprType) {
60 case SimpleExpr: break; // Nothing to do.
61 case CompoundStmt: break; // Nothing to do.
62 case CompoundLiteral:
63 // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
64 // postfix-expression exist, parse them now.
65 assert(0 && "FIXME");
66 break;
67 case CastExpr:
68 // We parsed '(' type-name ')' and the thing after it wasn't a '{'. Parse
69 // the cast-expression that follows it next.
70 ParseCastExpression();
71 break;
72 }
73 // If ParenExprType could have a postfix expr after it, handle it now.
Chris Lattner4564bc12006-08-10 23:14:52 +000074 assert(0);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000075}
76
77/// ParseUnaryExpression
78/// unary-expression: [C99 6.5.3]
79/// postfix-expression
80/// '++' unary-expression
81/// '--' unary-expression
82/// unary-operator cast-expression
83/// 'sizeof' unary-expression
84/// 'sizeof' '(' type-name ')'
85/// [GNU] '__alignof' unary-expression
86/// [GNU] '__alignof' '(' type-name ')'
87/// [GNU] '&&' identifier
88/// unary-operator: one of
89/// '&' '*' '+' '-' '~' '!'
90/// [GNU] '__extension__' '__real' '__imag'
91///
92void Parser::ParseUnaryExpression() {
93 switch (Tok.getKind()) {
94 default: // unary-expression: postfix-expression
95 ParsePostfixExpression();
96 break;
97 case tok::plusplus: // unary-expression: '++' unary-expression
98 case tok::minusminus: // unary-expression: '--' unary-expression
99 ConsumeToken();
100 ParseUnaryExpression();
101 break;
102 case tok::amp: // unary-expression: '&' cast-expression
103 case tok::star: // unary-expression: '*' cast-expression
104 case tok::plus: // unary-expression: '+' cast-expression
105 case tok::minus: // unary-expression: '-' cast-expression
106 case tok::tilde: // unary-expression: '~' cast-expression
107 case tok::exclaim: // unary-expression: '!' cast-expression
108 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
109 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
110 //case tok::kw__extension__: [TODO]
111 ConsumeToken();
112 ParseCastExpression();
113 break;
114
115 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
116 // unary-expression: 'sizeof' '(' type-name ')'
117 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
118 // unary-expression: '__alignof' '(' type-name ')'
119 ParseSizeofAlignofExpression();
120 break;
121 case tok::ampamp: // unary-expression: '&&' identifier
122 Diag(Tok, diag::ext_gnu_address_of_label);
123 ConsumeToken();
124 if (Tok.getKind() == tok::identifier) {
125 ConsumeToken();
126 } else {
127 Diag(Tok, diag::err_expected_ident);
128 ConsumeToken(); // FIXME: Should just return error!
129 return;
130 }
131 break;
132 }
133}
134
135/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
136/// unary-expression: [C99 6.5.3]
137/// 'sizeof' unary-expression
138/// 'sizeof' '(' type-name ')'
139/// [GNU] '__alignof' unary-expression
140/// [GNU] '__alignof' '(' type-name ')'
141void Parser::ParseSizeofAlignofExpression() {
142 assert((Tok.getKind() == tok::kw_sizeof ||
143 Tok.getKind() == tok::kw___alignof) &&
144 "Not a sizeof/alignof expression!");
145 ConsumeToken();
146
147 // If the operand doesn't start with an '(', it must be an expression.
148 if (Tok.getKind() != tok::l_paren) {
149 ParseUnaryExpression();
150 return;
151 }
152
153 // If it starts with a '(', we know that it is either a parenthesized
154 // type-name, or it is a unary-expression that starts with a compound literal,
155 // or starts with a primary-expression that is a parenthesized expression.
Chris Lattner4add4e62006-08-11 01:33:00 +0000156 ParenParseOption ExprType = CastExpr;
157 ParseParenExpression(ExprType);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000158}
159
Chris Lattner52a99e52006-08-10 20:56:00 +0000160/// ParsePostfixExpression
161/// postfix-expression: [C99 6.5.2]
162/// primary-expression
163/// postfix-expression '[' expression ']'
164/// postfix-expression '(' argument-expression-list[opt] ')'
165/// postfix-expression '.' identifier
166/// postfix-expression '->' identifier
167/// postfix-expression '++'
168/// postfix-expression '--'
169/// '(' type-name ')' '{' initializer-list '}'
170/// '(' type-name ')' '{' initializer-list ',' '}'
171///
172/// argument-expression-list: [C99 6.5.2]
173/// argument-expression
174/// argument-expression-list ',' argument-expression
175///
176/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000177/// identifier
178/// constant
179/// string-literal
180/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +0000181/// '__func__' [C99 6.4.2.2]
182/// [GNU] '__FUNCTION__'
183/// [GNU] '__PRETTY_FUNCTION__'
184/// [GNU] '(' compound-statement ')'
185/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
186/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
187/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
188/// assign-expr ')'
189/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
190/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
191/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
192/// [OBC] '@protocol' '(' identifier ')' [TODO]
193/// [OBC] '@encode' '(' type-name ')' [TODO]
194/// [OBC] objc-string-literal [TODO]
195///
196/// constant: [C99 6.4.4]
197/// integer-constant
198/// floating-constant
199/// enumeration-constant -> identifier
200/// character-constant
201///
202/// [GNU] offsetof-member-designator:
203/// [GNU] identifier
204/// [GNU] offsetof-member-designator '.' identifier
205/// [GNU] offsetof-member-designator '[' expression ']'
206///
207void Parser::ParsePostfixExpression() {
208 // First step, parse the primary expression.
209 switch (Tok.getKind()) {
210 // primary-expression
211 case tok::identifier: // primary-expression: identifier
212 // constant: enumeration-constant
213 case tok::numeric_constant: // constant: integer-constant
214 // constant: floating-constant
215 case tok::char_constant: // constant: character-constant
216 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
217 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
218 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
219 ConsumeToken();
220 break;
221 case tok::string_literal: // primary-expression: string-literal
222 ParseStringLiteralExpression();
223 break;
Chris Lattner4add4e62006-08-11 01:33:00 +0000224 case tok::l_paren: { // primary-expr: '(' expression ')'
225 // primary-expr: '(' compound-statement ')'
226 // postfix-expr: '(' type-name ')' '{' init-list '}'
227 // postfix-expr: '(' type-name ')' '{' init-list ',' '}'
228 ParenParseOption ParenExprType = CompoundLiteral;
229 ParseParenExpression(ParenExprType);
Chris Lattner52a99e52006-08-10 20:56:00 +0000230 break;
Chris Lattner4add4e62006-08-11 01:33:00 +0000231 }
Chris Lattnerf8339772006-08-10 22:01:51 +0000232 case tok::kw___builtin_va_arg:
233 case tok::kw___builtin_offsetof:
234 case tok::kw___builtin_choose_expr:
235 case tok::kw___builtin_types_compatible_p:
236 assert(0 && "FIXME: UNIMP!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000237 default:
238 Diag(Tok, diag::err_expected_expression);
Chris Lattnerf8339772006-08-10 22:01:51 +0000239 // Guarantee forward progress.
240 // FIXME: this dies on 'if ({1; });'. Expression parsing should return a
241 // bool for failure. This will cause higher-level parsing stuff to do the
242 // right thing.
243 ConsumeToken();
Chris Lattner52a99e52006-08-10 20:56:00 +0000244 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000245 }
246
247 // Now that the primary-expression piece of the postfix-expression has been
248 // parsed, see if there are any postfix-expression pieces here.
249 SourceLocation Loc;
250 while (1) {
251 switch (Tok.getKind()) {
252 default:
253 return;
254 case tok::l_square: // postfix-expression: p-e '[' expression ']'
255 Loc = Tok.getLocation();
256 ConsumeBracket();
257 ParseExpression();
Chris Lattner4564bc12006-08-10 23:14:52 +0000258 // Match the ']'.
259 MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
Chris Lattnerf8339772006-08-10 22:01:51 +0000260 break;
261
262 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
263 Loc = Tok.getLocation();
264 ConsumeParen();
265
266 while (1) {
267 // FIXME: This should be argument-expression!
268 ParseAssignmentExpression();
269
270 if (Tok.getKind() != tok::comma)
271 break;
272 ConsumeToken(); // Next argument.
273 }
274
Chris Lattner4564bc12006-08-10 23:14:52 +0000275 // Match the ')'.
276 MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
Chris Lattnerf8339772006-08-10 22:01:51 +0000277 break;
278
279 case tok::arrow: // postfix-expression: p-e '->' identifier
280 case tok::period: // postfix-expression: p-e '.' identifier
281 ConsumeToken();
282 if (Tok.getKind() != tok::identifier) {
283 Diag(Tok, diag::err_expected_ident);
284 return;
285 }
286 ConsumeToken();
287 break;
288
289 case tok::plusplus: // postfix-expression: postfix-expression '++'
290 case tok::minusminus: // postfix-expression: postfix-expression '--'
291 ConsumeToken();
292 break;
293 }
294 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000295}
296
297/// ParseStringLiteralExpression - This handles the various token types that
298/// form string literals, and also handles string concatenation [C99 5.1.1.2,
299/// translation phase #6].
300///
301/// primary-expression: [C99 6.5.1]
302/// string-literal
303void Parser::ParseStringLiteralExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +0000304 assert(isTokenStringLiteral() && "Not a string literal!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000305 ConsumeStringToken();
306
307 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
308 // considered to be strings.
Chris Lattner4564bc12006-08-10 23:14:52 +0000309 while (isTokenStringLiteral())
Chris Lattner52a99e52006-08-10 20:56:00 +0000310 ConsumeStringToken();
311}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000312
Chris Lattnerc951dae2006-08-10 04:23:57 +0000313
Chris Lattner4add4e62006-08-11 01:33:00 +0000314/// ParseParenExpression - This parses the unit that starts with a '(' token,
315/// based on what is allowed by ExprType. The actual thing parsed is returned
316/// in ExprType.
317///
318/// primary-expression: [C99 6.5.1]
Chris Lattnerc951dae2006-08-10 04:23:57 +0000319/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000320/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
321/// postfix-expression: [C99 6.5.2]
322/// '(' type-name ')' '{' initializer-list '}'
323/// '(' type-name ')' '{' initializer-list ',' '}'
Chris Lattner4add4e62006-08-11 01:33:00 +0000324/// cast-expression: [C99 6.5.4]
325/// '(' type-name ')' cast-expression
Chris Lattnerf8339772006-08-10 22:01:51 +0000326///
Chris Lattner4add4e62006-08-11 01:33:00 +0000327void Parser::ParseParenExpression(ParenParseOption &ExprType) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000328 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
329 SourceLocation OpenLoc = Tok.getLocation();
330 ConsumeParen();
331
Chris Lattner4add4e62006-08-11 01:33:00 +0000332 if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace &&
Chris Lattnerf8339772006-08-10 22:01:51 +0000333 !getLang().NoExtensions) {
334 Diag(Tok, diag::ext_gnu_statement_expr);
335 ParseCompoundStatement();
Chris Lattner4add4e62006-08-11 01:33:00 +0000336 ExprType = CompoundStmt;
337 } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000338 // Otherwise, this is a compound expression.
339 ParseTypeName();
340
341 // Match the ')'.
342 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
343
Chris Lattner4add4e62006-08-11 01:33:00 +0000344 if (Tok.getKind() == tok::l_brace) {
345 ParseInitializer();
346 ExprType = CompoundLiteral;
347 } else if (ExprType == CastExpr) {
348 // Note that this doesn't parse the subsequence cast-expression.
349 ExprType = CastExpr;
350 } else {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000351 Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
352 return;
353 }
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000354 return;
Chris Lattner4add4e62006-08-11 01:33:00 +0000355 } else {
356 ParseExpression();
357 ExprType = SimpleExpr;
Chris Lattnerf8339772006-08-10 22:01:51 +0000358 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000359
Chris Lattner4564bc12006-08-10 23:14:52 +0000360 // Match the ')'.
361 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000362}