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

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

Issue 2632663002: Fasta analyzer AST builder. (Closed)
Patch Set: 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
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(
118 toAnalyzerToken(last), unescapeLastStringPart(last.value, quote))) ;
asgerf 2017/01/19 10:13:26 Long line
ahe 2017/01/19 10:59:45 Done.
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 print("""
201 Analyzer AST:
202 $body
asgerf 2017/01/19 10:13:26 Please remove these prints.
ahe 2017/01/19 10:59:45 Done.
203 """);
204 var kernel = toKernel(body, elementStore, library.library, scope);
205 print("""
206 Kernel from analyzer AST:
207 $kernel""");
208 if (member is ProcedureBuilder) {
209 ProcedureBuilder builder = member;
210 builder.body = kernel;
211 } else {
212 internalError("Internal error: expected procedure, but got: $member");
213 }
214 }
215
216 void beginCascade(Token token) {
217 debugEvent("beginCascade");
218 Expression expression = pop();
219 push(token);
220 if (expression is CascadeExpression) {
221 push(expression);
222 } else {
223 push(ast.cascadeExpression(expression, <Expression>[]));
224 }
225 push(NullValue.CascadeReceiver);
226 }
227
228 void endCascade() {
229 debugEvent("Cascade");
230 Expression expression = pop();
231 CascadeExpression receiver = pop();
232 pop(); // Token.
233 receiver.cascadeSections.add(expression);
234 push(receiver);
235 }
236
237 void handleBinaryExpression(Token token) {
238 debugEvent("BinaryExpression");
239 if (identical(".", token.stringValue) ||
240 identical("..", token.stringValue)) {
241 doDotExpression(token);
242 } else {
243 Expression right = pop();
244 Expression left = pop();
245 push(ast.binaryExpression(left, toAnalyzerToken(token), right));
246 }
247 }
248
249 void doDotExpression(Token token) {
250 Expression identifierOrInvoke = pop();
251 Expression receiver = pop();
252 if (identifierOrInvoke is SimpleIdentifier) {
253 push(ast.propertyAccess(receiver, toAnalyzerToken(token),
254 identifierOrInvoke));
255 } else if (identifierOrInvoke is MethodInvocation) {
256 assert(identifierOrInvoke.target == null);
257 identifierOrInvoke
258 ..target = receiver
259 ..operator = toAnalyzerToken(token);
260 push(identifierOrInvoke);
261 } else {
262 internalError("Unhandled property access: ${identifierOrInvoke.runtimeType }");
asgerf 2017/01/19 10:13:26 Long Lineâ„¢
ahe 2017/01/19 10:59:45 Done.
263 }
264 }
265
266 void handleLiteralInt(Token token) {
267 debugEvent("LiteralInt");
268 push(ast.integerLiteral(toAnalyzerToken(token), int.parse(token.value)));
269 }
270
271 void endReturnStatement(
272 bool hasExpression, Token beginToken, Token endToken) {
273 debugEvent("ReturnStatement");
274 Expression expression = hasExpression ? pop() : null;
275 push(ast.returnStatement(toAnalyzerToken(beginToken), expression,
276 toAnalyzerToken(endToken)));
277 }
278
279 void endIfStatement(Token ifToken, Token elseToken) {
280 Statement elsePart = popIfNotNull(elseToken);
281 Statement thenPart = pop();
282 Expression condition = pop();
283 BeginGroupToken leftParenthesis = ifToken.next;
284 push(ast.ifStatement(
285 toAnalyzerToken(ifToken), toAnalyzerToken(ifToken.next), condition,
286 toAnalyzerToken(leftParenthesis.endGroup), thenPart,
287 toAnalyzerToken(elseToken), elsePart));
288 }
289
290 void prepareInitializers() {
291 debugEvent("prepareInitializers");
292 }
293
294 void handleNoInitializers() {
295 debugEvent("NoInitializers");
296 }
297
298 void endInitializers(int count, Token beginToken, Token endToken) {
299 debugEvent("Initializers");
300 popList(count);
301 }
302
303 void endInitializer(Token assignmentOperator) {
304 debugEvent("Initializer");
305 assert(assignmentOperator.stringValue == "=");
306 Expression initializer = pop();
307 Identifier identifier = pop();
308 // TODO(ahe): Don't push initializers, instead install them.
309 push(ast.variableDeclaration(
310 identifier, toAnalyzerToken(assignmentOperator), initializer));
311 }
312
313 void endInitializedIdentifier() {
314 debugEvent("InitializedIdentifier");
315 AstNode node = pop();
316 VariableDeclaration variable;
317 if (node is VariableDeclaration) {
318 variable = node;
319 } else if (node is SimpleIdentifier) {
320 variable = ast.variableDeclaration(node, null, null);
321 } else {
322 internalError("unhandled identifier: ${node.runtimeType}");
323 }
324 push(variable);
325 scope[variable.name.name] = variable.name.staticElement =
326 new AnalyzerLocalVariableElemment(variable);
327 }
328
329 void endVariablesDeclaration(int count, Token endToken) {
330 debugEvent("VariablesDeclaration");
331 List<VariableDeclaration> variables = popList(count);
332 TypeName type = pop();
333 pop(); // Modifiers.
334 push(ast.variableDeclarationStatement(
335 ast.variableDeclarationList(null, null, null, type, variables),
336 toAnalyzerToken(endToken)));
337 }
338
339 void handleAssignmentExpression(Token token) {
340 debugEvent("AssignmentExpression");
341 Expression rhs = pop();
342 Expression lhs = pop();
343 push(ast.assignmentExpression(lhs, toAnalyzerToken(token), rhs));
344 }
345
346 void endBlock(int count, Token beginToken, Token endToken) {
347 debugEvent("Block");
348 List<Statement> statements = popList(count) ?? <Statement>[];
349 exitLocalScope();
350 push(ast.block(toAnalyzerToken(beginToken), statements,
351 toAnalyzerToken(endToken)));
352 }
353
354 void endForStatement(
355 int updateExpressionCount, Token beginToken, Token endToken) {
356 debugEvent("ForStatement");
357 Statement body = pop();
358 List<Expression> updates = popList(updateExpressionCount);
359 ExpressionStatement condition = pop();
360 VariableDeclarationStatement variables = pop();
361 exitContinueTarget();
362 exitBreakTarget();
363 exitLocalScope();
364 BeginGroupToken leftParenthesis = beginToken.next;
365 push(ast.forStatement(
366 toAnalyzerToken(beginToken),
367 toAnalyzerToken(leftParenthesis),
368 variables?.variables,
369 null, // initialization.
370 variables?.semicolon,
371 condition.expression,
372 condition.semicolon,
373 updates,
374 toAnalyzerToken(leftParenthesis.endGroup),
375 body));
376 }
377
378 void handleLiteralList(
379 int count, Token beginToken, Token constKeyword, Token endToken) {
380 debugEvent("LiteralList");
381 List<Expression> expressions = popList(count);
382 TypeArgumentList typeArguments = pop();
383 push(ast.listLiteral(
384 toAnalyzerToken(constKeyword),
385 typeArguments,
386 toAnalyzerToken(beginToken),
387 expressions,
388 toAnalyzerToken(endToken)));
389 }
390
391 void handleAsyncModifier(Token asyncToken, Token starToken) {
392 debugEvent("AsyncModifier");
393 push(asyncMarkerFromTokens(asyncToken, starToken));
394 }
395
396 void endAwaitExpression(Token beginToken, Token endToken) {
397 debugEvent("AwaitExpression");
398 push(ast.awaitExpression(toAnalyzerToken(beginToken), pop()));
399 }
400
401 void beginLiteralSymbol(Token token) {
402 isFirstIdentifier = false;
403 }
404
405 void handleLiteralBool(Token token) {
406 debugEvent("LiteralBool");
407 bool value = identical(token.stringValue, "true");
408 assert(value || identical(token.stringValue, "false"));
409 push(ast.booleanLiteral(toAnalyzerToken(token), value));
410 }
411
412 void handleLiteralDouble(Token token) {
413 debugEvent("LiteralDouble");
414 push(ast.doubleLiteral(toAnalyzerToken(token), double.parse(token.value)));
415 }
416
417 void handleLiteralNull(Token token) {
418 debugEvent("LiteralNull");
419 push(ast.nullLiteral(toAnalyzerToken(token)));
420 }
421
422 void handleLiteralMap(
423 int count, Token beginToken, Token constKeyword, Token endToken) {
424 debugEvent("LiteralMap");
425 List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[];
426 TypeArgumentList typeArguments = pop();
427 push(ast.mapLiteral(toAnalyzerToken(constKeyword), typeArguments,
428 toAnalyzerToken(beginToken), entries, toAnalyzerToken(endToken)));
429 }
430
431 void endLiteralMapEntry(Token colon, Token endToken) {
432 debugEvent("LiteralMapEntry");
433 Expression value = pop();
434 Expression key = pop();
435 push(ast.mapLiteralEntry(key, toAnalyzerToken(colon), value));
436 }
437
438 void endLiteralSymbol(Token hashToken, int identifierCount) {
439 debugEvent("LiteralSymbol");
440 List<analyzer.Token> components = new List<analyzer.Token>(identifierCount);
441 for (int i = identifierCount - 1; i >= 0; i--) {
442 SimpleIdentifier identifier = pop();
443 components[i] = identifier.token;
444 }
445 push(ast.symbolLiteral(toAnalyzerToken(hashToken), components));
446 }
447
448 void endType(Token beginToken, Token endToken) {
449 debugEvent("Type");
450 TypeArgumentList arguments = pop();
451 SimpleIdentifier name = pop();
452 KernelClassElement cls = name.staticElement;
453 if (cls == null) {
454 Builder builder = scope.lookup(name.name);
455 if (builder == null) {
456 internalError("Undefined name: $name");
457 }
458 cls = elementStore[builder];
459 assert(cls != null);
460 name.staticElement = cls;
461 }
462 push(ast.typeName(name, arguments)..type = cls.rawType);
463 }
464
465 void handleAsOperator(Token operator, Token endToken) {
466 debugEvent("AsOperator");
467 TypeName type = pop();
468 Expression expression = pop();
469 push(ast.asExpression(expression, toAnalyzerToken(operator), type));
470 }
471
472 void handleIsOperator(Token operator, Token not, Token endToken) {
473 debugEvent("IsOperator");
474 TypeName type = pop();
475 Expression expression = pop();
476 push(ast.isExpression(expression, toAnalyzerToken(operator),
477 toAnalyzerToken(not), type));
478 }
479
480 void handleConditionalExpression(Token question, Token colon) {
481 debugEvent("ConditionalExpression");
482 Expression elseExpression = pop();
483 Expression thenExpression = pop();
484 Expression condition = pop();
485 push(ast.conditionalExpression(condition, toAnalyzerToken(question),
486 thenExpression, toAnalyzerToken(colon), elseExpression));
487 }
488
489 void endThrowExpression(Token throwToken, Token endToken) {
490 debugEvent("ThrowExpression");
491 push(ast.throwExpression(toAnalyzerToken(throwToken), pop()));
492 }
493
494 void endFormalParameter(Token thisKeyword) {
495 debugEvent("FormalParameter");
496 if (thisKeyword != null) {
497 internalError("'this' can't be used here.");
498 }
499 SimpleIdentifier name = pop();
500 TypeName type = pop();
501 pop(); // Modifiers.
502 pop(); // Metadata.
503 SimpleFormalParameter node = ast.simpleFormalParameter(null, null,
504 toAnalyzerToken(thisKeyword), type, name);
505 scope[name.name] = name.staticElement = new AnalyzerParameterElement(node);
506 push(node);
507 }
508
509 void endFormalParameters(int count, Token beginToken, Token endToken) {
510 debugEvent("FormalParameters");
511 List<FormalParameter> parameters = popList(count) ?? <FormalParameter>[];
512 push(ast.formalParameterList(toAnalyzerToken(beginToken), parameters,
513 null, null, toAnalyzerToken(endToken)));
514 }
515
516 void handleCatchBlock(Token onKeyword, Token catchKeyword) {
517 debugEvent("CatchBlock");
518 Block body = pop();
519 FormalParameterList catchParameters = popIfNotNull(catchKeyword);
520 if (catchKeyword != null) {
521 exitLocalScope();
522 }
523 TypeName type = popIfNotNull(onKeyword);
524 SimpleIdentifier exception;
525 SimpleIdentifier stackTrace;
526 if (catchParameters != null) {
527 if (catchParameters.length > 0) {
528 exception = catchParameters.parameters[0].identifier;
529 }
530 if (catchParameters.length > 1) {
531 stackTrace = catchParameters.parameters[1].identifier;
532 }
533 }
534 BeginGroupToken leftParenthesis = catchKeyword.next;
535 push(ast.catchClause(toAnalyzerToken(onKeyword), type,
536 toAnalyzerToken(catchKeyword), toAnalyzerToken(leftParenthesis),
537 exception, null, stackTrace,
538 toAnalyzerToken(leftParenthesis.endGroup), body));
539 }
540
541 void endTryStatement(
542 int catchCount, Token tryKeyword, Token finallyKeyword) {
543 Block finallyBlock = popIfNotNull(finallyKeyword);
544 List<CatchClause> catchClauses = popList(catchCount);
545 Block body = pop();
546 push(ast.tryStatement(toAnalyzerToken(tryKeyword), body, catchClauses,
547 toAnalyzerToken(finallyKeyword), finallyBlock));
548 }
549
550 void handleNoExpression(Token token) {
551 debugEvent("NoExpression");
552 push(NullValue.Expression);
553 }
554
555 void handleIndexedExpression(
556 Token openCurlyBracket, Token closeCurlyBracket) {
557 debugEvent("IndexedExpression");
558 Expression index = pop();
559 Expression target = pop();
560 if (target == null) {
561 CascadeExpression receiver = pop();
562 Token token = peek();
563 push(receiver);
564 IndexExpression expression = ast.indexExpressionForCascade(
565 toAnalyzerToken(token), toAnalyzerToken(openCurlyBracket), index,
566 toAnalyzerToken(closeCurlyBracket));
567 assert(expression.isCascaded);
568 push(expression);
569 } else {
570 push(ast.indexExpressionForTarget(target,
571 toAnalyzerToken(openCurlyBracket), index,
572 toAnalyzerToken(closeCurlyBracket)));
573 }
574 }
575
576 void handleUnaryPrefixExpression(Token token) {
577 debugEvent("UnaryPrefixExpression");
578 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
579 }
580
581 void handleUnaryPrefixAssignmentExpression(Token token) {
582 debugEvent("UnaryPrefixAssignmentExpression");
583 push(ast.prefixExpression(toAnalyzerToken(token), pop()));
584 }
585
586 void handleUnaryPostfixAssignmentExpression(Token token) {
587 debugEvent("UnaryPostfixAssignmentExpression");
588 push(ast.postfixExpression(pop(), toAnalyzerToken(token)));
589 }
590
591 void handleModifier(Token token) {
592 debugEvent("Modifier");
593 // TODO(ahe): Don't ignore modifiers.
594 }
595
596 void handleModifiers(int count) {
597 debugEvent("Modifiers");
598 // TODO(ahe): Don't ignore modifiers.
599 push(NullValue.Modifiers);
600 }
601 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698