blob: 91090d9ed75b356de679e1a928077602f6afe1ed [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();
Chris Lattnera092cd1f2006-08-11 01:38:28 +000024
25 if (Tok.getKind() == tok::numeric_constant)
26 ConsumeToken();
27
Chris Lattnerf5fbd792006-08-10 23:56:11 +000028 // FIXME: initializer-list
29 // Match the '}'.
30 MatchRHSPunctuation(tok::r_brace, Tok.getLocation(), "{",
31 diag::err_expected_rbrace);
32 return;
33 }
34
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000035 ParseAssignmentExpression();
36}
37
38
39
Chris Lattnerc951dae2006-08-10 04:23:57 +000040Parser::ExprTy Parser::ParseExpression() {
Chris Lattnereaf06592006-08-11 02:02:23 +000041 ParseCastExpression(false);
Chris Lattnerc951dae2006-08-10 04:23:57 +000042 return 0;
43}
44
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000045// Expr that doesn't include commas.
46void Parser::ParseAssignmentExpression() {
47 ParseExpression();
48}
49
Chris Lattnereaf06592006-08-11 02:02:23 +000050/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
51/// true, parse a unary-expression.
52///
Chris Lattner4564bc12006-08-10 23:14:52 +000053/// cast-expression: [C99 6.5.4]
54/// unary-expression
55/// '(' type-name ')' cast-expression
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000056/// unary-expression: [C99 6.5.3]
57/// postfix-expression
58/// '++' unary-expression
59/// '--' unary-expression
60/// unary-operator cast-expression
61/// 'sizeof' unary-expression
62/// 'sizeof' '(' type-name ')'
63/// [GNU] '__alignof' unary-expression
64/// [GNU] '__alignof' '(' type-name ')'
65/// [GNU] '&&' identifier
66/// unary-operator: one of
67/// '&' '*' '+' '-' '~' '!'
68/// [GNU] '__extension__' '__real' '__imag'
69///
Chris Lattnereaf06592006-08-11 02:02:23 +000070///
71void Parser::ParseCastExpression(bool isUnaryExpression) {
72 // If this doesn't start with an '(', then it is a unary-expression.
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000073 switch (Tok.getKind()) {
Chris Lattnereaf06592006-08-11 02:02:23 +000074 case tok::l_paren:
75 // If this expression is limited to being a unary-expression, the parent can
76 // not start a cast expression.
77 ParenParseOption ParenExprType =
78 isUnaryExpression ? CompoundLiteral : CastExpr;
79 ParseParenExpression(ParenExprType);
80
81 switch (ParenExprType) {
82 case SimpleExpr: return; // Nothing else to do.
83 case CompoundStmt: return; // Nothing else to do.
84 case CompoundLiteral:
85 // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
86 // postfix-expression exist, parse them now.
87 //Diag(Tok, diag::err_parse_error);
88 //assert(0 && "FIXME");
89 return;
90 case CastExpr:
91 // We parsed '(' type-name ')' and the thing after it wasn't a '{'. Parse
92 // the cast-expression that follows it next.
93 ParseCastExpression(false);
94 return;
95 }
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000096 default: // unary-expression: postfix-expression
97 ParsePostfixExpression();
98 break;
99 case tok::plusplus: // unary-expression: '++' unary-expression
100 case tok::minusminus: // unary-expression: '--' unary-expression
101 ConsumeToken();
Chris Lattnereaf06592006-08-11 02:02:23 +0000102 ParseCastExpression(true);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000103 break;
104 case tok::amp: // unary-expression: '&' cast-expression
105 case tok::star: // unary-expression: '*' cast-expression
106 case tok::plus: // unary-expression: '+' cast-expression
107 case tok::minus: // unary-expression: '-' cast-expression
108 case tok::tilde: // unary-expression: '~' cast-expression
109 case tok::exclaim: // unary-expression: '!' cast-expression
110 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
111 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
112 //case tok::kw__extension__: [TODO]
113 ConsumeToken();
Chris Lattnereaf06592006-08-11 02:02:23 +0000114 ParseCastExpression(false);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000115 break;
116
117 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
118 // unary-expression: 'sizeof' '(' type-name ')'
119 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
120 // unary-expression: '__alignof' '(' type-name ')'
121 ParseSizeofAlignofExpression();
122 break;
123 case tok::ampamp: // unary-expression: '&&' identifier
124 Diag(Tok, diag::ext_gnu_address_of_label);
125 ConsumeToken();
126 if (Tok.getKind() == tok::identifier) {
127 ConsumeToken();
128 } else {
129 Diag(Tok, diag::err_expected_ident);
130 ConsumeToken(); // FIXME: Should just return error!
131 return;
132 }
133 break;
134 }
135}
136
137/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
138/// unary-expression: [C99 6.5.3]
139/// 'sizeof' unary-expression
140/// 'sizeof' '(' type-name ')'
141/// [GNU] '__alignof' unary-expression
142/// [GNU] '__alignof' '(' type-name ')'
143void Parser::ParseSizeofAlignofExpression() {
144 assert((Tok.getKind() == tok::kw_sizeof ||
145 Tok.getKind() == tok::kw___alignof) &&
146 "Not a sizeof/alignof expression!");
147 ConsumeToken();
148
149 // If the operand doesn't start with an '(', it must be an expression.
150 if (Tok.getKind() != tok::l_paren) {
Chris Lattnereaf06592006-08-11 02:02:23 +0000151 ParseCastExpression(true);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000152 return;
153 }
154
155 // If it starts with a '(', we know that it is either a parenthesized
156 // type-name, or it is a unary-expression that starts with a compound literal,
157 // or starts with a primary-expression that is a parenthesized expression.
Chris Lattner4add4e62006-08-11 01:33:00 +0000158 ParenParseOption ExprType = CastExpr;
159 ParseParenExpression(ExprType);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000160}
161
Chris Lattner52a99e52006-08-10 20:56:00 +0000162/// ParsePostfixExpression
163/// postfix-expression: [C99 6.5.2]
164/// primary-expression
165/// postfix-expression '[' expression ']'
166/// postfix-expression '(' argument-expression-list[opt] ')'
167/// postfix-expression '.' identifier
168/// postfix-expression '->' identifier
169/// postfix-expression '++'
170/// postfix-expression '--'
171/// '(' type-name ')' '{' initializer-list '}'
172/// '(' type-name ')' '{' initializer-list ',' '}'
173///
174/// argument-expression-list: [C99 6.5.2]
175/// argument-expression
176/// argument-expression-list ',' argument-expression
177///
178/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000179/// identifier
180/// constant
181/// string-literal
182/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +0000183/// '__func__' [C99 6.4.2.2]
184/// [GNU] '__FUNCTION__'
185/// [GNU] '__PRETTY_FUNCTION__'
186/// [GNU] '(' compound-statement ')'
187/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
188/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
189/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
190/// assign-expr ')'
191/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
192/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
193/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
194/// [OBC] '@protocol' '(' identifier ')' [TODO]
195/// [OBC] '@encode' '(' type-name ')' [TODO]
196/// [OBC] objc-string-literal [TODO]
197///
198/// constant: [C99 6.4.4]
199/// integer-constant
200/// floating-constant
201/// enumeration-constant -> identifier
202/// character-constant
203///
204/// [GNU] offsetof-member-designator:
205/// [GNU] identifier
206/// [GNU] offsetof-member-designator '.' identifier
207/// [GNU] offsetof-member-designator '[' expression ']'
208///
209void Parser::ParsePostfixExpression() {
210 // First step, parse the primary expression.
211 switch (Tok.getKind()) {
212 // primary-expression
213 case tok::identifier: // primary-expression: identifier
214 // constant: enumeration-constant
215 case tok::numeric_constant: // constant: integer-constant
216 // constant: floating-constant
217 case tok::char_constant: // constant: character-constant
218 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
219 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
220 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
221 ConsumeToken();
222 break;
223 case tok::string_literal: // primary-expression: string-literal
224 ParseStringLiteralExpression();
225 break;
Chris Lattner4add4e62006-08-11 01:33:00 +0000226 case tok::l_paren: { // primary-expr: '(' expression ')'
227 // primary-expr: '(' compound-statement ')'
228 // postfix-expr: '(' type-name ')' '{' init-list '}'
229 // postfix-expr: '(' type-name ')' '{' init-list ',' '}'
230 ParenParseOption ParenExprType = CompoundLiteral;
231 ParseParenExpression(ParenExprType);
Chris Lattner52a99e52006-08-10 20:56:00 +0000232 break;
Chris Lattner4add4e62006-08-11 01:33:00 +0000233 }
Chris Lattnerf8339772006-08-10 22:01:51 +0000234 case tok::kw___builtin_va_arg:
235 case tok::kw___builtin_offsetof:
236 case tok::kw___builtin_choose_expr:
237 case tok::kw___builtin_types_compatible_p:
238 assert(0 && "FIXME: UNIMP!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000239 default:
240 Diag(Tok, diag::err_expected_expression);
Chris Lattnerf8339772006-08-10 22:01:51 +0000241 // Guarantee forward progress.
242 // FIXME: this dies on 'if ({1; });'. Expression parsing should return a
243 // bool for failure. This will cause higher-level parsing stuff to do the
244 // right thing.
245 ConsumeToken();
Chris Lattner52a99e52006-08-10 20:56:00 +0000246 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000247 }
248
249 // Now that the primary-expression piece of the postfix-expression has been
250 // parsed, see if there are any postfix-expression pieces here.
251 SourceLocation Loc;
252 while (1) {
253 switch (Tok.getKind()) {
254 default:
255 return;
256 case tok::l_square: // postfix-expression: p-e '[' expression ']'
257 Loc = Tok.getLocation();
258 ConsumeBracket();
259 ParseExpression();
Chris Lattner4564bc12006-08-10 23:14:52 +0000260 // Match the ']'.
261 MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
Chris Lattnerf8339772006-08-10 22:01:51 +0000262 break;
263
264 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
265 Loc = Tok.getLocation();
266 ConsumeParen();
267
268 while (1) {
269 // FIXME: This should be argument-expression!
270 ParseAssignmentExpression();
271
272 if (Tok.getKind() != tok::comma)
273 break;
274 ConsumeToken(); // Next argument.
275 }
276
Chris Lattner4564bc12006-08-10 23:14:52 +0000277 // Match the ')'.
278 MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
Chris Lattnerf8339772006-08-10 22:01:51 +0000279 break;
280
281 case tok::arrow: // postfix-expression: p-e '->' identifier
282 case tok::period: // postfix-expression: p-e '.' identifier
283 ConsumeToken();
284 if (Tok.getKind() != tok::identifier) {
285 Diag(Tok, diag::err_expected_ident);
286 return;
287 }
288 ConsumeToken();
289 break;
290
291 case tok::plusplus: // postfix-expression: postfix-expression '++'
292 case tok::minusminus: // postfix-expression: postfix-expression '--'
293 ConsumeToken();
294 break;
295 }
296 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000297}
298
299/// ParseStringLiteralExpression - This handles the various token types that
300/// form string literals, and also handles string concatenation [C99 5.1.1.2,
301/// translation phase #6].
302///
303/// primary-expression: [C99 6.5.1]
304/// string-literal
305void Parser::ParseStringLiteralExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +0000306 assert(isTokenStringLiteral() && "Not a string literal!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000307 ConsumeStringToken();
308
309 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
310 // considered to be strings.
Chris Lattner4564bc12006-08-10 23:14:52 +0000311 while (isTokenStringLiteral())
Chris Lattner52a99e52006-08-10 20:56:00 +0000312 ConsumeStringToken();
313}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000314
Chris Lattnerc951dae2006-08-10 04:23:57 +0000315
Chris Lattner4add4e62006-08-11 01:33:00 +0000316/// ParseParenExpression - This parses the unit that starts with a '(' token,
317/// based on what is allowed by ExprType. The actual thing parsed is returned
318/// in ExprType.
319///
320/// primary-expression: [C99 6.5.1]
Chris Lattnerc951dae2006-08-10 04:23:57 +0000321/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000322/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
323/// postfix-expression: [C99 6.5.2]
324/// '(' type-name ')' '{' initializer-list '}'
325/// '(' type-name ')' '{' initializer-list ',' '}'
Chris Lattner4add4e62006-08-11 01:33:00 +0000326/// cast-expression: [C99 6.5.4]
327/// '(' type-name ')' cast-expression
Chris Lattnerf8339772006-08-10 22:01:51 +0000328///
Chris Lattner4add4e62006-08-11 01:33:00 +0000329void Parser::ParseParenExpression(ParenParseOption &ExprType) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000330 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
331 SourceLocation OpenLoc = Tok.getLocation();
332 ConsumeParen();
333
Chris Lattner4add4e62006-08-11 01:33:00 +0000334 if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace &&
Chris Lattnerf8339772006-08-10 22:01:51 +0000335 !getLang().NoExtensions) {
336 Diag(Tok, diag::ext_gnu_statement_expr);
337 ParseCompoundStatement();
Chris Lattner4add4e62006-08-11 01:33:00 +0000338 ExprType = CompoundStmt;
339 } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000340 // Otherwise, this is a compound expression.
341 ParseTypeName();
342
343 // Match the ')'.
344 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
345
Chris Lattner4add4e62006-08-11 01:33:00 +0000346 if (Tok.getKind() == tok::l_brace) {
347 ParseInitializer();
348 ExprType = CompoundLiteral;
349 } else if (ExprType == CastExpr) {
350 // Note that this doesn't parse the subsequence cast-expression.
351 ExprType = CastExpr;
352 } else {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000353 Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
354 return;
355 }
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000356 return;
Chris Lattner4add4e62006-08-11 01:33:00 +0000357 } else {
358 ParseExpression();
359 ExprType = SimpleExpr;
Chris Lattnerf8339772006-08-10 22:01:51 +0000360 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000361
Chris Lattner4564bc12006-08-10 23:14:52 +0000362 // Match the ')'.
363 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000364}