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

Side by Side Diff: pkg/fasta/lib/src/analyzer/ast_builder.dart

Issue 2632663002: Fasta analyzer AST builder. (Closed)
Patch Set: Address review comments. Created 3 years, 11 months 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
« no previous file with comments | « pkg/fasta/lib/src/analyzer/analyzer.dart ('k') | pkg/fasta/lib/src/analyzer/element_store.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4
5 library fasta.analyzer.ast_builder;
6
7 import 'package:dart_scanner/src/token.dart' show
8 BeginGroupToken,
9 Token;
10
11 import 'package:analyzer/analyzer.dart';
12
13 import 'package:analyzer/dart/ast/token.dart' as analyzer show
14 Token;
15
16 import 'package:analyzer/dart/element/element.dart' show
17 Element;
18
19 import 'package:analyzer/dart/ast/ast_factory.dart' show
20 AstFactory;
21
22 import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
23
24 import '../errors.dart' show
25 internalError;
26
27 import '../source/scope_listener.dart' show
28 JumpTargetKind,
29 NullValue,
30 Scope,
31 ScopeListener;
32
33 import '../kernel/kernel_builder.dart' show
34 Builder,
35 KernelLibraryBuilder,
36 ProcedureBuilder;
37
38 import '../quote.dart';
39
40 import '../source/outline_builder.dart' show
41 asyncMarkerFromTokens;
42
43 import 'element_store.dart' show
44 AnalyzerLocalVariableElemment,
45 AnalyzerParameterElement,
46 ElementStore,
47 KernelClassElement;
48
49 import 'token_utils.dart' show
50 toAnalyzerToken;
51
52 import 'analyzer.dart' show
53 toKernel;
54
55 class AstBuilder extends ScopeListener {
56 final AstFactory ast = standard.astFactory;
57
58 final KernelLibraryBuilder library;
59
60 final Builder member;
61
62 final ElementStore elementStore;
63
64 bool isFirstIdentifier = false;
65
66 AstBuilder(this.library, this.member, this.elementStore, Scope scope)
67 : super(scope);
68
69 Uri get uri => library.uri;
70
71 createJumpTarget(JumpTargetKind kind) {
72 // TODO(ahe): Implement jump targets.
73 return null;
74 }
75
76 void beginLiteralString(Token token) {
77 debugEvent("beginLiteralString");
78 push(token);
79 }
80
81 void handleStringPart(Token token) {
82 debugEvent("StringPart");
83 push(token);
84 }
85
86 void doStringPart(Token token) {
87 push(ast.simpleStringLiteral(toAnalyzerToken(token), token.value));
88 }
89
90 void endLiteralString(int interpolationCount) {
91 debugEvent("endLiteralString");
92 if (interpolationCount == 0) {
93 Token token = pop();
94 String value = unescapeString(token.value);
95 push(ast.simpleStringLiteral(toAnalyzerToken(token), value));
96 } else {
97 List parts = popList(1 + interpolationCount * 2);
98 Token first = parts.first;
99 Token last = parts.last;
100 Quote quote = analyzeQuote(first.value);
101 List<InterpolationElement> elements = <InterpolationElement>[];
102 elements.add(ast.interpolationString(
103 toAnalyzerToken(first),
104 unescapeFirstStringPart(first.value, quote)));
105 for (int i = 1; i < parts.length - 1; i++) {
106 var part = parts[i];
107 if (part is Token) {
108 elements.add(ast.interpolationString(
109 toAnalyzerToken(part), part.value));
110 } else if (part is Expression) {
111 elements.add(ast.interpolationExpression(null, part, null));
112 } else {
113 internalError(
114 "Unexpected part in string interpolation: ${part.runtimeType}");
115 }
116 }
117 elements.add(ast.interpolationString(toAnalyzerToken(last),
118 unescapeLastStringPart(last.value, quote)));
119 push(ast.stringInterpolation(elements));
120 }
121 }
122
123 void handleStringJuxtaposition(int literalCount) {
124 debugEvent("StringJuxtaposition");
125 push(ast.adjacentStrings(popList(literalCount)));
126 }
127
128 void endArguments(int count, Token beginToken, Token endToken) {
129 debugEvent("Arguments");
130 List expressions = popList(count);
131 ArgumentList arguments = ast.argumentList(toAnalyzerToken(beginToken),
132 expressions, toAnalyzerToken(endToken));
133 push(ast.methodInvocation(null, null, null, null, arguments));
134 }
135
136 void beginExpression(Token token) {
137 isFirstIdentifier = true;
138 }
139
140 void handleIdentifier(Token token) {
141 debugEvent("handleIdentifier");
142 String name = token.value;
143 SimpleIdentifier identifier = ast.simpleIdentifier(toAnalyzerToken(token));
144 if (isFirstIdentifier) {
145 Builder builder = scope.lookup(name);
146 if (builder != null) {
147 Element element = elementStore[builder];
148 assert(element != null);
149 identifier.staticElement = element;
150 }
151 }
152 push(identifier);
153 isFirstIdentifier = false;
154 }
155
156 void endSend(Token token) {
157 debugEvent("Send");
158 MethodInvocation arguments = pop();
159 TypeArgumentList typeArguments = pop();
160 if (arguments != null) {
161 if (typeArguments != null) {
162 arguments.typeArguments = typeArguments;
163 }
164 doInvocation(token, arguments);
165 } else {
166 doPropertyGet(token);
167 }
168 }
169
170 void doInvocation(Token token, MethodInvocation arguments) {
171 Expression receiver = pop();
172 if (receiver is SimpleIdentifier) {
173 arguments.methodName = receiver;
174 push(arguments);
175 } else {
176 internalError("Unhandled receiver in send: ${receiver.runtimeType}");
177 }
178 }
179
180 void doPropertyGet(Token token) {
181 }
182
183 void endExpressionStatement(Token token) {
184 debugEvent("ExpressionStatement");
185 push(ast.expressionStatement(pop(), toAnalyzerToken(token)));
186 }
187
188 void endFunctionBody(int count, Token beginToken, Token endToken) {
189 debugEvent("FunctionBody");
190 List statements = popList(count);
191 if (beginToken != null) {
192 exitLocalScope();
193 }
194 push(ast.block(toAnalyzerToken(beginToken), statements,
195 toAnalyzerToken(endToken)));
196 }
197
198 void finishFunction(formals, asyncModifier, Statement body) {
199 debugEvent("finishFunction");
200 var kernel = toKernel(body, elementStore, library.library, scope);
201 if (member is ProcedureBuilder) {
202 ProcedureBuilder builder = member;
203 builder.body = kernel;
204 } else {
205 internalError("Internal error: expected procedure, but got: $member");
206 }
207 }
208
209 void beginCascade(Token token) {
210 debugEvent("beginCascade");
211 Expression expression = pop();
212 push(token);
213 if (expression is CascadeExpression) {
214 push(expression);
215 } else {
216 push(ast.cascadeExpression(expression, <Expression>[]));
217 }
218 push(NullValue.CascadeReceiver);
219 }
220
221 void endCascade() {
222 debugEvent("Cascade");
223 Expression expression = pop();
224 CascadeExpression receiver = pop();
225 pop(); // Token.
226 receiver.cascadeSections.add(expression);
227 push(receiver);
228 }
229
230 void handleBinaryExpression(Token token) {
231 debugEvent("BinaryExpression");
232 if (identical(".", token.stringValue) ||
233 identical("..", token.stringValue)) {
234 doDotExpression(token);
235 } else {
236 Expression right = pop();
237 Expression left = pop();
238 push(ast.binaryExpression(left, toAnalyzerToken(token), right));
239 }
240 }
241
242 void doDotExpression(Token token) {
243 Expression identifierOrInvoke = pop();
244 Expression receiver = pop();
245 if (identifierOrInvoke is SimpleIdentifier) {
246 push(ast.propertyAccess(receiver, toAnalyzerToken(token),
247 identifierOrInvoke));
248 } else if (identifierOrInvoke is MethodInvocation) {
249 assert(identifierOrInvoke.target == null);
250 identifierOrInvoke
251 ..target = receiver
252 ..operator = toAnalyzerToken(token);
253 push(identifierOrInvoke);
254 } else {
255 internalError(
256 "Unhandled property access: ${identifierOrInvoke.runtimeType}");
257 }
258 }
259
260 void handleLiteralInt(Token token) {
261 debugEvent("LiteralInt");
262 push(ast.integerLiteral(toAnalyzerToken(token), int.parse(token.value)));
263 }
264
265 void endReturnStatement(
266 bool hasExpression, Token beginToken, Token endToken) {
267 debugEvent("ReturnStatement");
268 Expression expression = hasExpression ? pop() : null;
269 push(ast.returnStatement(toAnalyzerToken(beginToken), expression,
270 toAnalyzerToken(endToken)));
271 }
272
273 void endIfStatement(Token ifToken, Token elseToken) {
274 Statement elsePart = popIfNotNull(elseToken);
275 Statement thenPart = pop();
276 Expression condition = pop();
277 BeginGroupToken leftParenthesis = ifToken.next;
278 push(ast.ifStatement(
279 toAnalyzerToken(ifToken), toAnalyzerToken(ifToken.next), condition,
280 toAnalyzerToken(leftParenthesis.endGroup), thenPart,
281 toAnalyzerToken(elseToken), elsePart));
282 }
283
284 void prepareInitializers() {
285 debugEvent("prepareInitializers");
286 }
287
288 void handleNoInitializers() {
289 debugEvent("NoInitializers");
290 }
291
292 void endInitializers(int count, Token beginToken, Token endToken) {
293 debugEvent("Initializers");
294 popList(count);
295 }
296
297 void endInitializer(Token assignmentOperator) {
298 debugEvent("Initializer");
299 assert(assignmentOperator.stringValue == "=");
300 Expression initializer = pop();
301 Identifier identifier = pop();
302 // TODO(ahe): Don't push initializers, instead install them.
303 push(ast.variableDeclaration(
304 identifier, toAnalyzerToken(assignmentOperator), initializer));
305 }
306
307 void endInitializedIdentifier() {
308 debugEvent("InitializedIdentifier");
309 AstNode node = pop();
310 VariableDeclaration variable;
311 if (node is VariableDeclaration) {
312 variable = node;
313 } else if (node is SimpleIdentifier) {
314 variable = ast.variableDeclaration(node, null, null);
315 } else {
316 internalError("unhandled identifier: ${node.runtimeType}");
317 }
318 push(variable);
319 scope[variable.name.name] = variable.name.staticElement =
320 new AnalyzerLocalVariableElemment(variable);
321 }
322
323 void endVariablesDeclaration(int count, Token endToken) {
324 debugEvent("VariablesDeclaration");
325 List<VariableDeclaration> variables = popList(count);
326 TypeName type = pop();
327 pop(); // Modifiers.
328 push(ast.variableDeclarationStatement(
329 ast.variableDeclarationList(null, null, null, type, variables),
330 toAnalyzerToken(endToken)));
331 }
332
333 void handleAssignmentExpression(Token token) {
334 debugEvent("AssignmentExpression");
335 Expression rhs = pop();
336 Expression lhs = pop();
337 push(ast.assignmentExpression(lhs, toAnalyzerToken(token), rhs));
338 }
339
340 void endBlock(int count, Token beginToken, Token endToken) {
341 debugEvent("Block");
342 List<Statement> statements = popList(count) ?? <Statement>[];
343 exitLocalScope();
344 push(ast.block(toAnalyzerToken(beginToken), statements,
345 toAnalyzerToken(endToken)));
346 }
347
348 void endForStatement(
349 int updateExpressionCount, Token beginToken, Token endToken) {
350 debugEvent("ForStatement");
351 Statement body = pop();
352 List<Expression> updates = popList(updateExpressionCount);
353 ExpressionStatement condition = pop();
354 VariableDeclarationStatement variables = pop();
355 exitContinueTarget();
356 exitBreakTarget();
357 exitLocalScope();
358 BeginGroupToken leftParenthesis = beginToken.next;
359 push(ast.forStatement(
360 toAnalyzerToken(beginToken),
361 toAnalyzerToken(leftParenthesis),
362 variables?.variables,
363 null, // initialization.
364 variables?.semicolon,
365 condition.expression,
366 condition.semicolon,
367 updates,
368 toAnalyzerToken(leftParenthesis.endGroup),
369 body));
370 }
371
372 void handleLiteralList(
373 int count, Token beginToken, Token constKeyword, Token endToken) {
374 debugEvent("LiteralList");
375 List<Expression> expressions = popList(count);
376 TypeArgumentList typeArguments = pop();
377 push(ast.listLiteral(
378 toAnalyzerToken(constKeyword),
379 typeArguments,
380 toAnalyzerToken(beginToken),
381 expressions,
382 toAnalyzerToken(endToken)));
383 }
384
385 void handleAsyncModifier(Token asyncToken, Token starToken) {
386 debugEvent("AsyncModifier");
387 push(asyncMarkerFromTokens(asyncToken, starToken));
388 }
389
390 void endAwaitExpression(Token beginToken, Token endToken) {
391 debugEvent("AwaitExpression");
392 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop()));
393 }
394
395 void beginLiteralSymbol(Token token) {
396 isFirstIdentifier = false;
397 }
398
399 void handleLiteralBool(Token token) {
400 debugEvent("LiteralBool");
401 bool value = identical(token.stringValue, "true");
402 assert(value || identical(token.stringValue, "false"));
403 push(ast.booleanLiteral(toAnalyzerToken(token), value));
404 }
405
406 void handleLiteralDouble(Token token) {
407 debugEvent("LiteralDouble");
408 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.value)));
409 }
410
411 void handleLiteralNull(Token token) {
412 debugEvent("LiteralNull");
413 push(ast.nullLiteral(toAnalyzerToken(token)));
414 }
415
416 void handleLiteralMap(
417 int count, Token beginToken, Token constKeyword, Token endToken) {
418 debugEvent("LiteralMap");
419 List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[];
420 TypeArgumentList typeArguments = pop();
421 push(ast.mapLiteral(toAnalyzerToken(constKeyword), typeArguments,
422 toAnalyzerToken(beginToken), entries, toAnalyzerToken(endToken)));
423 }
424
425 void endLiteralMapEntry(Token colon, Token endToken) {
426 debugEvent("LiteralMapEntry");
427 Expression value = pop();
428 Expression key = pop();
429 push(ast.mapLiteralEntry(key, toAnalyzerToken(colon), value));
430 }
431
432 void endLiteralSymbol(Token hashToken, int identifierCount) {
433 debugEvent("LiteralSymbol");
434 List<analyzer.Token> components = new List<analyzer.Token>(identifierCount);
435 for (int i = identifierCount - 1; i >= 0; i--) {
436 SimpleIdentifier identifier = pop();
437 components[i] = identifier.token;
438 }
439 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components));
440 }
441
442 void endType(Token beginToken, Token endToken) {
443 debugEvent("Type");
444 TypeArgumentList arguments = pop();
445 SimpleIdentifier name = pop();
446 KernelClassElement cls = name.staticElement;
447 if (cls == null) {
448 Builder builder = scope.lookup(name.name);
449 if (builder == null) {
450 internalError("Undefined name: $name");
451 }
452 cls = elementStore[builder];
453 assert(cls != null);
454 name.staticElement = cls;
455 }
456 push(ast.typeName(name, arguments)..type = cls.rawType);
457 }
458
459 void handleAsOperator(Token operator, Token endToken) {
460 debugEvent("AsOperator");
461 TypeName type = pop();
462 Expression expression = pop();
463 push(ast.asExpression(expression, toAnalyzerToken(operator), type));
464 }
465
466 void handleIsOperator(Token operator, Token not, Token endToken) {
467 debugEvent("IsOperator");
468 TypeName type = pop();
469 Expression expression = pop();
470 push(ast.isExpression(expression, toAnalyzerToken(operator),
471 toAnalyzerToken(not), type));
472 }
473
474 void handleConditionalExpression(Token question, Token colon) {
475 debugEvent("ConditionalExpression");
476 Expression elseExpression = pop();
477 Expression thenExpression = pop();
478 Expression condition = pop();
479 push(ast.conditionalExpression(condition, toAnalyzerToken(question),
480 thenExpression, toAnalyzerToken(colon), elseExpression));
481 }
482
483 void endThrowExpression(Token throwToken, Token endToken) {
484 debugEvent("ThrowExpression");
485 push(ast.throwExpression(toAnalyzerToken(throwToken), pop()));
486 }
487
488 void endFormalParameter(Token thisKeyword) {
489 debugEvent("FormalParameter");
490 if (thisKeyword != null) {
491 internalError("'this' can't be used here.");
492 }
493 SimpleIdentifier name = pop();
494 TypeName type = pop();
495 pop(); // Modifiers.
496 pop(); // Metadata.
497 SimpleFormalParameter node = ast.simpleFormalParameter(null, null,
498 toAnalyzerToken(thisKeyword), type, name);
499 scope[name.name] = name.staticElement = new AnalyzerParameterElement(node);
500 push(node);
501 }
502
503 void endFormalParameters(int count, Token beginToken, Token endToken) {
504 debugEvent("FormalParameters");
505 List<FormalParameter> parameters = popList(count) ?? <FormalParameter>[];
506 push(ast.formalParameterList(toAnalyzerToken(beginToken), parameters,
507 null, null, toAnalyzerToken(endToken)));
508 }
509
510 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
511 debugEvent("CatchBlock");
512 Block body = pop();
513 FormalParameterList catchParameters = popIfNotNull(catchKeyword);
514 if (catchKeyword != null) {
515 exitLocalScope();
516 }
517 TypeName type = popIfNotNull(onKeyword);
518 SimpleIdentifier exception;
519 SimpleIdentifier stackTrace;
520 if (catchParameters != null) {
521 if (catchParameters.length > 0) {
522 exception = catchParameters.parameters[0].identifier;
523 }
524 if (catchParameters.length > 1) {
525 stackTrace = catchParameters.parameters[1].identifier;
526 }
527 }
528 BeginGroupToken leftParenthesis = catchKeyword.next;
529 push(ast.catchClause(toAnalyzerToken(onKeyword), type,
530 toAnalyzerToken(catchKeyword), toAnalyzerToken(leftParenthesis),
531 exception, null, stackTrace,
532 toAnalyzerToken(leftParenthesis.endGroup), body));
533 }
534
535 void endTryStatement(
536 int catchCount, Token tryKeyword, Token finallyKeyword) {
537 Block finallyBlock = popIfNotNull(finallyKeyword);
538 List<CatchClause> catchClauses = popList(catchCount);
539 Block body = pop();
540 push(ast.tryStatement(toAnalyzerToken(tryKeyword), body, catchClauses,
541 toAnalyzerToken(finallyKeyword), finallyBlock));
542 }
543
544 void handleNoExpression(Token token) {
545 debugEvent("NoExpression");
546 push(NullValue.Expression);
547 }
548
549 void handleIndexedExpression(
550 Token openCurlyBracket, Token closeCurlyBracket) {
551 debugEvent("IndexedExpression");
552 Expression index = pop();
553 Expression target = pop();
554 if (target == null) {
555 CascadeExpression receiver = pop();
556 Token token = peek();
557 push(receiver);
558 IndexExpression expression = ast.indexExpressionForCascade(
559 toAnalyzerToken(token), toAnalyzerToken(openCurlyBracket), index,
560 toAnalyzerToken(closeCurlyBracket));
561 assert(expression.isCascaded);
562 push(expression);
563 } else {
564 push(ast.indexExpressionForTarget(target,
565 toAnalyzerToken(openCurlyBracket), index,
566 toAnalyzerToken(closeCurlyBracket)));
567 }
568 }
569
570 void handleUnaryPrefixExpression(Token token) {
571 debugEvent("UnaryPrefixExpression");
572 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
573 }
574
575 void handleUnaryPrefixAssignmentExpression(Token token) {
576 debugEvent("UnaryPrefixAssignmentExpression");
577 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
578 }
579
580 void handleUnaryPostfixAssignmentExpression(Token token) {
581 debugEvent("UnaryPostfixAssignmentExpression");
582 push(ast.postfixExpression(pop(), toAnalyzerToken(token)));
583 }
584
585 void handleModifier(Token token) {
586 debugEvent("Modifier");
587 // TODO(ahe): Don't ignore modifiers.
588 }
589
590 void handleModifiers(int count) {
591 debugEvent("Modifiers");
592 // TODO(ahe): Don't ignore modifiers.
593 push(NullValue.Modifiers);
594 }
595 }
OLDNEW
« no previous file with comments | « pkg/fasta/lib/src/analyzer/analyzer.dart ('k') | pkg/fasta/lib/src/analyzer/element_store.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698