Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: dart/frog/leg/scanner/parser.dart

Issue 8508016: Create class AST nodes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * An event generating parser of Dart programs. This parser expects 6 * An event generating parser of Dart programs. This parser expects
7 * all tokens in a linked list. 7 * all tokens in a linked list.
8 */ 8 */
9 class Parser<L extends Listener> { 9 class PartialParser<L extends Listener> {
10 final L listener; 10 final L listener;
11 Function beginTypeArguments;
kasperl 2011/11/10 06:37:34 I think these function fields deserve a comment. W
ahe 2011/11/10 07:59:46 I'll wrap these in a class and clean it up. After
12 Function parseTypeFunction;
13 Function endTypeArguments;
14 Function handleNoTypeArguments;
11 15
12 Parser(L this.listener); 16 Function beginTypeVariables;
17 Function parseTypeVariableFunction;
18 Function endTypeVariables;
19 Function handleNoTypeVariables;
20
21 PartialParser(L this.listener) {
22 beginTypeArguments = listener.beginTypeArguments;
23 parseTypeFunction = parseType;
24 endTypeArguments = listener.endTypeArguments;
25 handleNoTypeArguments = listener.handleNoTypeArguments;
26
27 beginTypeVariables = listener.beginTypeVariables;
28 parseTypeVariableFunction = parseTypeVariable;
29 endTypeVariables = listener.endTypeVariables;
30 handleNoTypeVariables = listener.handleNoTypeVariables;
31 }
13 32
14 // TODO(ahe): Rename this method. It is too subtle compared to token.next. 33 // TODO(ahe): Rename this method. It is too subtle compared to token.next.
15 Token next(Token token) => checkEof(token.next); 34 Token next(Token token) => checkEof(token.next);
16 35
17 Token checkEof(Token token) { 36 Token checkEof(Token token) {
18 if (token.kind === EOF_TOKEN) { 37 if (token.kind === EOF_TOKEN) {
19 listener.unexpectedEof(); 38 listener.unexpectedEof();
20 throw 'Unexpected EOF'; 39 throw 'Unexpected EOF';
21 } 40 }
22 return token; 41 return token;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 token = next(token); 181 token = next(token);
163 } while (token !== null); 182 } while (token !== null);
164 throw 'Internal error: unreachable code'; 183 throw 'Internal error: unreachable code';
165 } 184 }
166 185
167 Token parseClass(Token token) { 186 Token parseClass(Token token) {
168 Token begin = token; 187 Token begin = token;
169 listener.beginClass(token); 188 listener.beginClass(token);
170 token = parseIdentifier(next(token)); 189 token = parseIdentifier(next(token));
171 token = parseTypeVariablesOpt(token); 190 token = parseTypeVariablesOpt(token);
172 token = parseSuperclassClauseOpt(token); 191 Token extendsKeyword;
173 token = parseImplementsOpt(token); 192 if (optional('extends', token)) {
193 extendsKeyword = token;
194 token = parseType(next(token));
195 } else {
196 extendsKeyword = null;
197 listener.handleNoType(token);
ngeoffray 2011/11/10 08:27:42 Should that be handleNoSuperType instead?
ahe 2011/11/10 13:37:23 Not necessarily. I could change it if someone has
198 }
199 Token implementsKeyword;
200 int interfacesCount = 0;
201 if (optional('implements', token)) {
202 do {
203 token = parseType(next(token));
204 ++interfacesCount;
205 } while (optional(',', token));
206 }
174 token = parseNativeClassClauseOpt(token); 207 token = parseNativeClassClauseOpt(token);
175 token = parseClassBody(token); 208 token = parseClassBody(token);
176 listener.endClass(begin, token); 209 listener.endClass(interfacesCount, begin, extendsKeyword, implementsKeyword,
210 token);
177 return token.next; 211 return token.next;
178 } 212 }
179 213
180 Token parseNativeClassClauseOpt(Token token) { 214 Token parseNativeClassClauseOpt(Token token) {
181 if (optional('native', token)) { 215 if (optional('native', token)) {
182 return parseString(next(token)); 216 return parseString(next(token));
183 } 217 }
184 return token; 218 return token;
185 } 219 }
186 220
187 Token parseString(Token token) { 221 Token parseString(Token token) {
188 if (token.kind === STRING_TOKEN) { 222 if (token.kind === STRING_TOKEN) {
189 return next(token); 223 return next(token);
190 } else { 224 } else {
191 return listener.expected('string', token); 225 return listener.expected('string', token);
192 } 226 }
193 } 227 }
194 228
195 Token parseIdentifier(Token token) { 229 Token parseIdentifier(Token token) {
196 if (isIdentifier(token)) { 230 if (isIdentifier(token)) {
197 listener.handleIdentifier(token); 231 listener.handleIdentifier(token);
198 } else { 232 } else {
199 listener.expectedIdentifier(token); 233 listener.expectedIdentifier(token);
200 } 234 }
201 return next(token); 235 return next(token);
202 } 236 }
203 237
204 Token parseTypeVariablesOpt(Token token) {
205 if (!optional('<', token)) {
206 listener.handleNoTypeVariables(token);
207 return token;
208 }
209 return parseTypeVariables(token);
210 }
211
212 Token parseTypeVariables(Token token) {
213 expect('<', token);
214 listener.beginTypeVariables(token);
215 do {
216 token = parseTypeVariable(next(token));
217 } while (optional(',', token));
218 listener.endTypeVariables(token);
219 return expect('>', token);
220 }
221
222 Token expect(String string, Token token) { 238 Token expect(String string, Token token) {
223 if (string !== token.stringValue) { 239 if (string !== token.stringValue) {
224 return listener.expected(string, token); 240 return listener.expected(string, token);
225 } 241 }
226 return token.next; 242 return token.next;
227 } 243 }
228 244
229 Token parseTypeVariable(Token token) { 245 Token parseTypeVariable(Token token) {
230 listener.beginTypeVariable(token); 246 listener.beginTypeVariable(token);
231 token = parseIdentifier(token); 247 token = parseIdentifier(token);
232 token = parseSuperclassClauseOpt(token); 248 if (optional('extends', token)) {
249 token = parseType(next(token));
250 } else {
251 listener.handleNoType(token);
252 }
233 listener.endTypeVariable(token); 253 listener.endTypeVariable(token);
234 return token; 254 return token;
235 } 255 }
236 256
237 bool optional(String value, Token token) => value === token.stringValue; 257 bool optional(String value, Token token) => value === token.stringValue;
238 258
239 Token parseSuperclassClauseOpt(Token token) {
240 if (optional('extends', token)) {
241 return parseType(next(token));
242 }
243 return token;
244 }
245
246 Token parseType(Token token) { 259 Token parseType(Token token) {
247 // TODO(ahe): Rename this method to parseTypeOrVar? 260 // TODO(ahe): Rename this method to parseTypeOrVar?
248 if (isIdentifier(token)) { 261 if (isIdentifier(token)) {
249 token = parseIdentifier(token); 262 token = parseIdentifier(token);
250 while (optional('.', token)) { 263 while (optional('.', token)) {
251 // TODO(ahe): Validate that there are at most two identifiers. 264 // TODO(ahe): Validate that there are at most two identifiers.
252 token = parseIdentifier(next(token)); 265 token = parseIdentifier(next(token));
253 } 266 }
254 } else if (optional('var', token)) { 267 } else if (optional('var', token)) {
255 listener.handleVarKeyword(token); 268 listener.handleVarKeyword(token);
256 listener.endType(token); 269 listener.endType(token);
257 return next(token); 270 return next(token);
258 } else { 271 } else {
259 token = listener.expectedType(token); 272 token = listener.expectedType(token);
260 } 273 }
261 token = parseTypeArgumentsOpt(token); 274 token = parseTypeArgumentsOpt(token);
262 listener.endType(token); 275 listener.endType(token);
263 return token; 276 return token;
264 } 277 }
265 278
266 Token parseTypeArgumentsOpt(Token token) { 279 Token parseTypeArgumentsOpt(Token token) {
280 return parseStuff(token, beginTypeArguments, parseTypeFunction,
281 endTypeArguments, handleNoTypeArguments);
282 }
283
284 Token parseTypeVariablesOpt(Token token) {
285 return parseStuff(token, beginTypeVariables, parseTypeVariableFunction,
286 endTypeVariables, handleNoTypeVariables);
287 }
288
289 Token parseStuff(Token token, Function beginStuff, Function stuffParser,
kasperl 2011/11/10 06:37:34 It would be nice with a more saying name for this.
ahe 2011/11/10 13:37:23 Added TODO.
290 Function endStuff, Function handleNoStuff) {
267 if (optional('<', token)) { 291 if (optional('<', token)) {
268 listener.beginTypeArguments(next(token)); 292 Token begin = token;
293 beginStuff(begin);
294 int count = 0;
269 do { 295 do {
270 token = parseType(next(token)); 296 token = stuffParser(next(token));
297 ++count;
271 } while (optional(',', token)); 298 } while (optional(',', token));
299 endStuff(count, begin, token);
272 return expect('>', token); 300 return expect('>', token);
273 } 301 }
302 handleNoStuff(token);
274 return token; 303 return token;
275 } 304 }
276 305
277 Token parseImplementsOpt(Token token) {
278 if (optional('implements', token)) {
279 do {
280 token = parseType(next(token));
281 } while (optional(',', token));
282 }
283 return token;
284 }
285
286 Token parseClassBody(Token token) => skipBlock(token); 306 Token parseClassBody(Token token) => skipBlock(token);
287 307
288 Token parseTopLevelMember(Token token) { 308 Token parseTopLevelMember(Token token) {
289 Token start = token; 309 Token start = token;
290 listener.beginTopLevelMember(token); 310 listener.beginTopLevelMember(token);
291 Token previous = token; 311 Token previous = token;
292 LOOP: while (token !== null) { 312 LOOP: while (token !== null) {
293 final kind = token.kind; 313 final kind = token.kind;
294 switch (true) { 314 switch (true) {
295 case kind === LBRACE_TOKEN: 315 case kind === LBRACE_TOKEN:
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 while (token !== null && 361 while (token !== null &&
342 token.kind !== LPAREN_TOKEN && 362 token.kind !== LPAREN_TOKEN &&
343 token.kind !== RPAREN_TOKEN) { 363 token.kind !== RPAREN_TOKEN) {
344 token = next(token); 364 token = next(token);
345 } 365 }
346 token = expect(')', token); 366 token = expect(')', token);
347 return expect(';', token); 367 return expect(';', token);
348 } 368 }
349 } 369 }
350 370
351 class BodyParser extends Parser/* <BodyListener> Frog bug #320 */ { 371 class Parser extends PartialParser/* <NodeListener> Frog bug #320 */ {
352 BodyParser(BodyListener listener) : super(listener); 372 Parser(NodeListener listener) : super(listener);
353 373
354 Token parseFunction(Token token) { 374 Token parseFunction(Token token) {
355 listener.beginFunction(token); 375 listener.beginFunction(token);
356 token = parseReturnTypeOpt(token); 376 token = parseReturnTypeOpt(token);
357 listener.beginFunctionName(token); 377 listener.beginFunctionName(token);
358 token = parseIdentifier(token); 378 token = parseIdentifier(token);
359 listener.endFunctionName(token); 379 listener.endFunctionName(token);
360 token = parseFormalParameters(token); 380 token = parseFormalParameters(token);
361 return parseFunctionBody(token); 381 return parseFunctionBody(token);
362 } 382 }
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 if (optional(';', token)) { 725 if (optional(';', token)) {
706 listener.endRethrowStatement(throwToken, token); 726 listener.endRethrowStatement(throwToken, token);
707 return token.next; 727 return token.next;
708 } else { 728 } else {
709 token = parseExpression(token); 729 token = parseExpression(token);
710 listener.endThrowStatement(throwToken, token); 730 listener.endThrowStatement(throwToken, token);
711 return expectSemicolon(token); 731 return expectSemicolon(token);
712 } 732 }
713 } 733 }
714 } 734 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698