blob: 5e84832b3321197c9911f7a51f0664c141b19ef4 [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 Lattnerf5fbd792006-08-10 23:56:11 +000056#if 0
Chris Lattner4564bc12006-08-10 23:14:52 +000057 // Otherwise this is either a cast, a compound literal, or a parenthesized
58 // expression.
59 SourceLocation LParenLoc = Tok.getLocation();
60 ConsumeParen();
Chris Lattnerf5fbd792006-08-10 23:56:11 +000061#endif
Chris Lattner4564bc12006-08-10 23:14:52 +000062
63 assert(0);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000064}
65
66/// ParseUnaryExpression
67/// unary-expression: [C99 6.5.3]
68/// postfix-expression
69/// '++' unary-expression
70/// '--' unary-expression
71/// unary-operator cast-expression
72/// 'sizeof' unary-expression
73/// 'sizeof' '(' type-name ')'
74/// [GNU] '__alignof' unary-expression
75/// [GNU] '__alignof' '(' type-name ')'
76/// [GNU] '&&' identifier
77/// unary-operator: one of
78/// '&' '*' '+' '-' '~' '!'
79/// [GNU] '__extension__' '__real' '__imag'
80///
81void Parser::ParseUnaryExpression() {
82 switch (Tok.getKind()) {
83 default: // unary-expression: postfix-expression
84 ParsePostfixExpression();
85 break;
86 case tok::plusplus: // unary-expression: '++' unary-expression
87 case tok::minusminus: // unary-expression: '--' unary-expression
88 ConsumeToken();
89 ParseUnaryExpression();
90 break;
91 case tok::amp: // unary-expression: '&' cast-expression
92 case tok::star: // unary-expression: '*' cast-expression
93 case tok::plus: // unary-expression: '+' cast-expression
94 case tok::minus: // unary-expression: '-' cast-expression
95 case tok::tilde: // unary-expression: '~' cast-expression
96 case tok::exclaim: // unary-expression: '!' cast-expression
97 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
98 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
99 //case tok::kw__extension__: [TODO]
100 ConsumeToken();
101 ParseCastExpression();
102 break;
103
104 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
105 // unary-expression: 'sizeof' '(' type-name ')'
106 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
107 // unary-expression: '__alignof' '(' type-name ')'
108 ParseSizeofAlignofExpression();
109 break;
110 case tok::ampamp: // unary-expression: '&&' identifier
111 Diag(Tok, diag::ext_gnu_address_of_label);
112 ConsumeToken();
113 if (Tok.getKind() == tok::identifier) {
114 ConsumeToken();
115 } else {
116 Diag(Tok, diag::err_expected_ident);
117 ConsumeToken(); // FIXME: Should just return error!
118 return;
119 }
120 break;
121 }
122}
123
124/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
125/// unary-expression: [C99 6.5.3]
126/// 'sizeof' unary-expression
127/// 'sizeof' '(' type-name ')'
128/// [GNU] '__alignof' unary-expression
129/// [GNU] '__alignof' '(' type-name ')'
130void Parser::ParseSizeofAlignofExpression() {
131 assert((Tok.getKind() == tok::kw_sizeof ||
132 Tok.getKind() == tok::kw___alignof) &&
133 "Not a sizeof/alignof expression!");
134 ConsumeToken();
135
136 // If the operand doesn't start with an '(', it must be an expression.
137 if (Tok.getKind() != tok::l_paren) {
138 ParseUnaryExpression();
139 return;
140 }
141
142 // If it starts with a '(', we know that it is either a parenthesized
143 // type-name, or it is a unary-expression that starts with a compound literal,
144 // or starts with a primary-expression that is a parenthesized expression.
145 SourceLocation LParenLoc = Tok.getLocation();
146 ConsumeParen();
147
148 if (isTypeSpecifierQualifier()) {
149 // This is now known to be either a parenthesized type-name, or a compound
150 // literal.
151
152
153 // FIXME: ParseTypeName.
154 assert(0 && "implement!");
155 } else {
156 // Otherwise, this is known to be a parenthesized-expression. Parse the
157 // rest of the parethesized-expression here.
158 ParseExpression();
159
160 }
161
Chris Lattner4564bc12006-08-10 23:14:52 +0000162 // Match the ')'.
163 MatchRHSPunctuation(tok::r_paren, LParenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000164}
165
Chris Lattner52a99e52006-08-10 20:56:00 +0000166/// ParsePostfixExpression
167/// postfix-expression: [C99 6.5.2]
168/// primary-expression
169/// postfix-expression '[' expression ']'
170/// postfix-expression '(' argument-expression-list[opt] ')'
171/// postfix-expression '.' identifier
172/// postfix-expression '->' identifier
173/// postfix-expression '++'
174/// postfix-expression '--'
175/// '(' type-name ')' '{' initializer-list '}'
176/// '(' type-name ')' '{' initializer-list ',' '}'
177///
178/// argument-expression-list: [C99 6.5.2]
179/// argument-expression
180/// argument-expression-list ',' argument-expression
181///
182/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000183/// identifier
184/// constant
185/// string-literal
186/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +0000187/// '__func__' [C99 6.4.2.2]
188/// [GNU] '__FUNCTION__'
189/// [GNU] '__PRETTY_FUNCTION__'
190/// [GNU] '(' compound-statement ')'
191/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
192/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
193/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
194/// assign-expr ')'
195/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
196/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
197/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
198/// [OBC] '@protocol' '(' identifier ')' [TODO]
199/// [OBC] '@encode' '(' type-name ')' [TODO]
200/// [OBC] objc-string-literal [TODO]
201///
202/// constant: [C99 6.4.4]
203/// integer-constant
204/// floating-constant
205/// enumeration-constant -> identifier
206/// character-constant
207///
208/// [GNU] offsetof-member-designator:
209/// [GNU] identifier
210/// [GNU] offsetof-member-designator '.' identifier
211/// [GNU] offsetof-member-designator '[' expression ']'
212///
213void Parser::ParsePostfixExpression() {
214 // First step, parse the primary expression.
215 switch (Tok.getKind()) {
216 // primary-expression
217 case tok::identifier: // primary-expression: identifier
218 // constant: enumeration-constant
219 case tok::numeric_constant: // constant: integer-constant
220 // constant: floating-constant
221 case tok::char_constant: // constant: character-constant
222 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
223 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
224 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
225 ConsumeToken();
226 break;
227 case tok::string_literal: // primary-expression: string-literal
228 ParseStringLiteralExpression();
229 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000230 case tok::l_paren: // primary-expression: '(' expression ')'
231 // primary-expression: '(' compound-statement ')'
232 ParseParenExpression(false/*allow statement exprs, initializers */);
Chris Lattner52a99e52006-08-10 20:56:00 +0000233 break;
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 Lattnerf8339772006-08-10 22:01:51 +0000316/// ParseParenExpression - C99 6.5.1p5
Chris Lattnerc951dae2006-08-10 04:23:57 +0000317/// primary-expression:
318/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000319/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
320/// postfix-expression: [C99 6.5.2]
321/// '(' type-name ')' '{' initializer-list '}'
322/// '(' type-name ')' '{' initializer-list ',' '}'
323///
324void Parser::ParseParenExpression(bool ParenExprOnly) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000325 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
326 SourceLocation OpenLoc = Tok.getLocation();
327 ConsumeParen();
328
Chris Lattnerf8339772006-08-10 22:01:51 +0000329 if (!ParenExprOnly && Tok.getKind() == tok::l_brace &&
330 !getLang().NoExtensions) {
331 Diag(Tok, diag::ext_gnu_statement_expr);
332 ParseCompoundStatement();
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000333 } else if (ParenExprOnly || !isTypeSpecifierQualifier()) {
Chris Lattnerf8339772006-08-10 22:01:51 +0000334 ParseExpression();
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000335 } else {
336 // Otherwise, this is a compound expression.
337 ParseTypeName();
338
339 // Match the ')'.
340 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
341
342 if (Tok.getKind() != tok::l_brace) {
343 Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
344 return;
345 }
346
347 ParseInitializer();
348 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000349 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000350
Chris Lattner4564bc12006-08-10 23:14:52 +0000351
352 // Match the ')'.
353 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000354}