blob: cf8a2f52135d1bbf1f87259080517c4fccfc6d2f [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 Lattner4564bc12006-08-10 23:14:52 +000037/// ParseCastExpression
38/// cast-expression: [C99 6.5.4]
39/// unary-expression
40/// '(' type-name ')' cast-expression
41///
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000042void Parser::ParseCastExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +000043 // If this doesn't start with an '(', then it is a unary-expression.
44 if (Tok.getKind() != tok::l_paren)
45 return ParseUnaryExpression();
46
47 // Otherwise this is either a cast, a compound literal, or a parenthesized
48 // expression.
49 SourceLocation LParenLoc = Tok.getLocation();
50 ConsumeParen();
51
52 assert(0);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000053}
54
55/// ParseUnaryExpression
56/// 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///
70void Parser::ParseUnaryExpression() {
71 switch (Tok.getKind()) {
72 default: // unary-expression: postfix-expression
73 ParsePostfixExpression();
74 break;
75 case tok::plusplus: // unary-expression: '++' unary-expression
76 case tok::minusminus: // unary-expression: '--' unary-expression
77 ConsumeToken();
78 ParseUnaryExpression();
79 break;
80 case tok::amp: // unary-expression: '&' cast-expression
81 case tok::star: // unary-expression: '*' cast-expression
82 case tok::plus: // unary-expression: '+' cast-expression
83 case tok::minus: // unary-expression: '-' cast-expression
84 case tok::tilde: // unary-expression: '~' cast-expression
85 case tok::exclaim: // unary-expression: '!' cast-expression
86 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
87 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
88 //case tok::kw__extension__: [TODO]
89 ConsumeToken();
90 ParseCastExpression();
91 break;
92
93 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
94 // unary-expression: 'sizeof' '(' type-name ')'
95 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
96 // unary-expression: '__alignof' '(' type-name ')'
97 ParseSizeofAlignofExpression();
98 break;
99 case tok::ampamp: // unary-expression: '&&' identifier
100 Diag(Tok, diag::ext_gnu_address_of_label);
101 ConsumeToken();
102 if (Tok.getKind() == tok::identifier) {
103 ConsumeToken();
104 } else {
105 Diag(Tok, diag::err_expected_ident);
106 ConsumeToken(); // FIXME: Should just return error!
107 return;
108 }
109 break;
110 }
111}
112
113/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
114/// unary-expression: [C99 6.5.3]
115/// 'sizeof' unary-expression
116/// 'sizeof' '(' type-name ')'
117/// [GNU] '__alignof' unary-expression
118/// [GNU] '__alignof' '(' type-name ')'
119void Parser::ParseSizeofAlignofExpression() {
120 assert((Tok.getKind() == tok::kw_sizeof ||
121 Tok.getKind() == tok::kw___alignof) &&
122 "Not a sizeof/alignof expression!");
123 ConsumeToken();
124
125 // If the operand doesn't start with an '(', it must be an expression.
126 if (Tok.getKind() != tok::l_paren) {
127 ParseUnaryExpression();
128 return;
129 }
130
131 // If it starts with a '(', we know that it is either a parenthesized
132 // type-name, or it is a unary-expression that starts with a compound literal,
133 // or starts with a primary-expression that is a parenthesized expression.
134 SourceLocation LParenLoc = Tok.getLocation();
135 ConsumeParen();
136
137 if (isTypeSpecifierQualifier()) {
138 // This is now known to be either a parenthesized type-name, or a compound
139 // literal.
140
141
142 // FIXME: ParseTypeName.
143 assert(0 && "implement!");
144 } else {
145 // Otherwise, this is known to be a parenthesized-expression. Parse the
146 // rest of the parethesized-expression here.
147 ParseExpression();
148
149 }
150
Chris Lattner4564bc12006-08-10 23:14:52 +0000151 // Match the ')'.
152 MatchRHSPunctuation(tok::r_paren, LParenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000153}
154
Chris Lattner52a99e52006-08-10 20:56:00 +0000155/// ParsePostfixExpression
156/// postfix-expression: [C99 6.5.2]
157/// primary-expression
158/// postfix-expression '[' expression ']'
159/// postfix-expression '(' argument-expression-list[opt] ')'
160/// postfix-expression '.' identifier
161/// postfix-expression '->' identifier
162/// postfix-expression '++'
163/// postfix-expression '--'
164/// '(' type-name ')' '{' initializer-list '}'
165/// '(' type-name ')' '{' initializer-list ',' '}'
166///
167/// argument-expression-list: [C99 6.5.2]
168/// argument-expression
169/// argument-expression-list ',' argument-expression
170///
171/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000172/// identifier
173/// constant
174/// string-literal
175/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +0000176/// '__func__' [C99 6.4.2.2]
177/// [GNU] '__FUNCTION__'
178/// [GNU] '__PRETTY_FUNCTION__'
179/// [GNU] '(' compound-statement ')'
180/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
181/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
182/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
183/// assign-expr ')'
184/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
185/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
186/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
187/// [OBC] '@protocol' '(' identifier ')' [TODO]
188/// [OBC] '@encode' '(' type-name ')' [TODO]
189/// [OBC] objc-string-literal [TODO]
190///
191/// constant: [C99 6.4.4]
192/// integer-constant
193/// floating-constant
194/// enumeration-constant -> identifier
195/// character-constant
196///
197/// [GNU] offsetof-member-designator:
198/// [GNU] identifier
199/// [GNU] offsetof-member-designator '.' identifier
200/// [GNU] offsetof-member-designator '[' expression ']'
201///
202void Parser::ParsePostfixExpression() {
203 // First step, parse the primary expression.
204 switch (Tok.getKind()) {
205 // primary-expression
206 case tok::identifier: // primary-expression: identifier
207 // constant: enumeration-constant
208 case tok::numeric_constant: // constant: integer-constant
209 // constant: floating-constant
210 case tok::char_constant: // constant: character-constant
211 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
212 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
213 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
214 ConsumeToken();
215 break;
216 case tok::string_literal: // primary-expression: string-literal
217 ParseStringLiteralExpression();
218 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000219 case tok::l_paren: // primary-expression: '(' expression ')'
220 // primary-expression: '(' compound-statement ')'
221 ParseParenExpression(false/*allow statement exprs, initializers */);
Chris Lattner52a99e52006-08-10 20:56:00 +0000222 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000223 case tok::kw___builtin_va_arg:
224 case tok::kw___builtin_offsetof:
225 case tok::kw___builtin_choose_expr:
226 case tok::kw___builtin_types_compatible_p:
227 assert(0 && "FIXME: UNIMP!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000228 default:
229 Diag(Tok, diag::err_expected_expression);
Chris Lattnerf8339772006-08-10 22:01:51 +0000230 // Guarantee forward progress.
231 // FIXME: this dies on 'if ({1; });'. Expression parsing should return a
232 // bool for failure. This will cause higher-level parsing stuff to do the
233 // right thing.
234 ConsumeToken();
Chris Lattner52a99e52006-08-10 20:56:00 +0000235 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000236 }
237
238 // Now that the primary-expression piece of the postfix-expression has been
239 // parsed, see if there are any postfix-expression pieces here.
240 SourceLocation Loc;
241 while (1) {
242 switch (Tok.getKind()) {
243 default:
244 return;
245 case tok::l_square: // postfix-expression: p-e '[' expression ']'
246 Loc = Tok.getLocation();
247 ConsumeBracket();
248 ParseExpression();
Chris Lattner4564bc12006-08-10 23:14:52 +0000249 // Match the ']'.
250 MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
Chris Lattnerf8339772006-08-10 22:01:51 +0000251 break;
252
253 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
254 Loc = Tok.getLocation();
255 ConsumeParen();
256
257 while (1) {
258 // FIXME: This should be argument-expression!
259 ParseAssignmentExpression();
260
261 if (Tok.getKind() != tok::comma)
262 break;
263 ConsumeToken(); // Next argument.
264 }
265
Chris Lattner4564bc12006-08-10 23:14:52 +0000266 // Match the ')'.
267 MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
Chris Lattnerf8339772006-08-10 22:01:51 +0000268 break;
269
270 case tok::arrow: // postfix-expression: p-e '->' identifier
271 case tok::period: // postfix-expression: p-e '.' identifier
272 ConsumeToken();
273 if (Tok.getKind() != tok::identifier) {
274 Diag(Tok, diag::err_expected_ident);
275 return;
276 }
277 ConsumeToken();
278 break;
279
280 case tok::plusplus: // postfix-expression: postfix-expression '++'
281 case tok::minusminus: // postfix-expression: postfix-expression '--'
282 ConsumeToken();
283 break;
284 }
285 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000286}
287
288/// ParseStringLiteralExpression - This handles the various token types that
289/// form string literals, and also handles string concatenation [C99 5.1.1.2,
290/// translation phase #6].
291///
292/// primary-expression: [C99 6.5.1]
293/// string-literal
294void Parser::ParseStringLiteralExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +0000295 assert(isTokenStringLiteral() && "Not a string literal!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000296 ConsumeStringToken();
297
298 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
299 // considered to be strings.
Chris Lattner4564bc12006-08-10 23:14:52 +0000300 while (isTokenStringLiteral())
Chris Lattner52a99e52006-08-10 20:56:00 +0000301 ConsumeStringToken();
302}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000303
Chris Lattnerc951dae2006-08-10 04:23:57 +0000304
Chris Lattnerf8339772006-08-10 22:01:51 +0000305/// ParseParenExpression - C99 6.5.1p5
Chris Lattnerc951dae2006-08-10 04:23:57 +0000306/// primary-expression:
307/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000308/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
309/// postfix-expression: [C99 6.5.2]
310/// '(' type-name ')' '{' initializer-list '}'
311/// '(' type-name ')' '{' initializer-list ',' '}'
312///
313void Parser::ParseParenExpression(bool ParenExprOnly) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000314 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
315 SourceLocation OpenLoc = Tok.getLocation();
316 ConsumeParen();
317
Chris Lattnerf8339772006-08-10 22:01:51 +0000318 if (!ParenExprOnly && Tok.getKind() == tok::l_brace &&
319 !getLang().NoExtensions) {
320 Diag(Tok, diag::ext_gnu_statement_expr);
321 ParseCompoundStatement();
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000322 } else if (!ParenExprOnly && isTypeSpecifierQualifier()) {
Chris Lattnerf8339772006-08-10 22:01:51 +0000323 // FIXME: Implement compound literals: C99 6.5.2.5. Type-name: C99 6.7.6.
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000324 assert(0 && "IMPLEMENT THIS!");
Chris Lattnerf8339772006-08-10 22:01:51 +0000325 } else {
326 ParseExpression();
327 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000328
Chris Lattner4564bc12006-08-10 23:14:52 +0000329
330 // Match the ')'.
331 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000332}