blob: ba5215af346f85ac4fb233ff96296c7e64c90f22 [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 Lattner52a99e52006-08-10 20:56:00 +000028 ParsePostfixExpression();
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 Lattner52a99e52006-08-10 20:56:00 +000037/// ParsePostfixExpression
38/// postfix-expression: [C99 6.5.2]
39/// primary-expression
40/// postfix-expression '[' expression ']'
41/// postfix-expression '(' argument-expression-list[opt] ')'
42/// postfix-expression '.' identifier
43/// postfix-expression '->' identifier
44/// postfix-expression '++'
45/// postfix-expression '--'
46/// '(' type-name ')' '{' initializer-list '}'
47/// '(' type-name ')' '{' initializer-list ',' '}'
48///
49/// argument-expression-list: [C99 6.5.2]
50/// argument-expression
51/// argument-expression-list ',' argument-expression
52///
53/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000054/// identifier
55/// constant
56/// string-literal
57/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +000058/// '__func__' [C99 6.4.2.2]
59/// [GNU] '__FUNCTION__'
60/// [GNU] '__PRETTY_FUNCTION__'
61/// [GNU] '(' compound-statement ')'
62/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
63/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
64/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
65/// assign-expr ')'
66/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
67/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
68/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
69/// [OBC] '@protocol' '(' identifier ')' [TODO]
70/// [OBC] '@encode' '(' type-name ')' [TODO]
71/// [OBC] objc-string-literal [TODO]
72///
73/// constant: [C99 6.4.4]
74/// integer-constant
75/// floating-constant
76/// enumeration-constant -> identifier
77/// character-constant
78///
79/// [GNU] offsetof-member-designator:
80/// [GNU] identifier
81/// [GNU] offsetof-member-designator '.' identifier
82/// [GNU] offsetof-member-designator '[' expression ']'
83///
84void Parser::ParsePostfixExpression() {
85 // First step, parse the primary expression.
86 switch (Tok.getKind()) {
87 // primary-expression
88 case tok::identifier: // primary-expression: identifier
89 // constant: enumeration-constant
90 case tok::numeric_constant: // constant: integer-constant
91 // constant: floating-constant
92 case tok::char_constant: // constant: character-constant
93 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
94 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
95 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
96 ConsumeToken();
97 break;
98 case tok::string_literal: // primary-expression: string-literal
99 ParseStringLiteralExpression();
100 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000101 case tok::l_paren: // primary-expression: '(' expression ')'
102 // primary-expression: '(' compound-statement ')'
103 ParseParenExpression(false/*allow statement exprs, initializers */);
Chris Lattner52a99e52006-08-10 20:56:00 +0000104 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000105 case tok::kw___builtin_va_arg:
106 case tok::kw___builtin_offsetof:
107 case tok::kw___builtin_choose_expr:
108 case tok::kw___builtin_types_compatible_p:
109 assert(0 && "FIXME: UNIMP!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000110 default:
111 Diag(Tok, diag::err_expected_expression);
Chris Lattnerf8339772006-08-10 22:01:51 +0000112 // Guarantee forward progress.
113 // FIXME: this dies on 'if ({1; });'. Expression parsing should return a
114 // bool for failure. This will cause higher-level parsing stuff to do the
115 // right thing.
116 ConsumeToken();
Chris Lattner52a99e52006-08-10 20:56:00 +0000117 return;
Chris Lattnerf8339772006-08-10 22:01:51 +0000118 }
119
120 // Now that the primary-expression piece of the postfix-expression has been
121 // parsed, see if there are any postfix-expression pieces here.
122 SourceLocation Loc;
123 while (1) {
124 switch (Tok.getKind()) {
125 default:
126 return;
127 case tok::l_square: // postfix-expression: p-e '[' expression ']'
128 Loc = Tok.getLocation();
129 ConsumeBracket();
130 ParseExpression();
131 if (Tok.getKind() == tok::r_square) {
132 ConsumeBracket();
133 } else {
134 Diag(Tok, diag::err_expected_rsquare);
135 Diag(Loc, diag::err_matching);
136 SkipUntil(tok::r_square);
137 }
138 break;
139
140 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
141 Loc = Tok.getLocation();
142 ConsumeParen();
143
144 while (1) {
145 // FIXME: This should be argument-expression!
146 ParseAssignmentExpression();
147
148 if (Tok.getKind() != tok::comma)
149 break;
150 ConsumeToken(); // Next argument.
151 }
152
153 if (Tok.getKind() == tok::r_paren) {
154 ConsumeParen();
155 } else {
156 Diag(Tok, diag::err_expected_rparen);
157 Diag(Loc, diag::err_matching);
158 SkipUntil(tok::r_paren);
159 }
160 break;
161
162 case tok::arrow: // postfix-expression: p-e '->' identifier
163 case tok::period: // postfix-expression: p-e '.' identifier
164 ConsumeToken();
165 if (Tok.getKind() != tok::identifier) {
166 Diag(Tok, diag::err_expected_ident);
167 return;
168 }
169 ConsumeToken();
170 break;
171
172 case tok::plusplus: // postfix-expression: postfix-expression '++'
173 case tok::minusminus: // postfix-expression: postfix-expression '--'
174 ConsumeToken();
175 break;
176 }
177 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000178}
179
180/// ParseStringLiteralExpression - This handles the various token types that
181/// form string literals, and also handles string concatenation [C99 5.1.1.2,
182/// translation phase #6].
183///
184/// primary-expression: [C99 6.5.1]
185/// string-literal
186void Parser::ParseStringLiteralExpression() {
187 assert(isStringLiteral() && "Not a string literal!");
188 ConsumeStringToken();
189
190 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
191 // considered to be strings.
192 while (isStringLiteral())
193 ConsumeStringToken();
194}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000195
Chris Lattnerc951dae2006-08-10 04:23:57 +0000196
Chris Lattnerf8339772006-08-10 22:01:51 +0000197/// ParseParenExpression - C99 6.5.1p5
Chris Lattnerc951dae2006-08-10 04:23:57 +0000198/// primary-expression:
199/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000200/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
201/// postfix-expression: [C99 6.5.2]
202/// '(' type-name ')' '{' initializer-list '}'
203/// '(' type-name ')' '{' initializer-list ',' '}'
204///
205void Parser::ParseParenExpression(bool ParenExprOnly) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000206 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
207 SourceLocation OpenLoc = Tok.getLocation();
208 ConsumeParen();
209
Chris Lattnerf8339772006-08-10 22:01:51 +0000210 if (!ParenExprOnly && Tok.getKind() == tok::l_brace &&
211 !getLang().NoExtensions) {
212 Diag(Tok, diag::ext_gnu_statement_expr);
213 ParseCompoundStatement();
214 } else if (!ParenExprOnly && 0 /*type */) {
215 // FIXME: Implement compound literals: C99 6.5.2.5. Type-name: C99 6.7.6.
216 } else {
217 ParseExpression();
218 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000219
220 if (Tok.getKind() == tok::r_paren) {
221 ConsumeParen();
222 } else {
223 Diag(Tok, diag::err_expected_rparen);
224 Diag(OpenLoc, diag::err_matching);
225 }
226}