blob: 2f477bb1464a260c4d3173037a6774804c1ba68d [file] [log] [blame]
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library fe.stack_listener;
import 'dart:collection' show Queue;
import 'package:front_end/src/fasta/parser/identifier_context.dart';
import 'package:front_end/src/fasta/parser/listener.dart';
import 'package:front_end/src/fasta/scanner/token.dart';
enum NullValue {
Arguments,
Combinators,
FormalParameters,
FunctionBody,
IdentifierList,
Initializers,
Metadata,
Modifiers,
Type,
TypeArguments,
TypeList,
TypeVariable,
TypeVariables,
}
abstract class StackListener extends Listener {
final Queue<Object> stack = new Queue<Object>();
Uri get uri;
void checkEmpty() {
if (stack.isNotEmpty) {
throw "Stack not empty $uri:\n"
" ${stack.join('\n ')}";
}
}
void debugEvent(String name) {
// print(" ${stack.join('\n ')}");
// print(name);
}
void endCompilationUnit(int count, Token token) {
debugEvent("CompilationUnit");
checkEmpty();
}
void endTopLevelDeclaration(Token token) {
debugEvent("TopLevelDeclaration");
checkEmpty();
}
void handleIdentifier(Token token, IdentifierContext context) {
debugEvent("handleIdentifier");
push(token.lexeme);
}
void handleNoArguments(Token token) {
debugEvent("NoArguments");
var typeArguments = pop();
assert(typeArguments == null);
push(NullValue.Arguments);
}
void handleNoFormalParameters(Token token) {
debugEvent("NoFormalParameters");
push(NullValue.FormalParameters);
}
void handleNoFunctionBody(Token token) {
debugEvent("NoFunctionBody");
push(NullValue.FunctionBody);
}
void handleNoInitializers() {
debugEvent("NoInitializers");
push(NullValue.Initializers);
}
void handleNoType(Token token) {
debugEvent("NoType");
push(NullValue.Type);
}
void handleNoTypeArguments(Token token) {
debugEvent("NoTypeArguments");
push(NullValue.TypeArguments);
}
void handleNoTypeVariables(Token token) {
debugEvent("NoTypeVariables");
push(NullValue.TypeVariables);
}
void handleParenthesizedExpression(BeginGroupToken token) {
debugEvent("ParenthesizedExpression");
}
void logEvent(String name) {
print(" ${stack.join('\n ')}");
throw "Unhandled event: $name in $runtimeType $uri.";
}
Object peek() {
Object node = stack.last;
return node is NullValue ? null : node;
}
Object pop({NullValue expect: null}) {
Object node = stack.removeLast();
if (expect != null && expect != node) {
throw "unexpected value: $expect vs $node";
}
return node is NullValue ? null : node;
}
Object popIfNotNull(Object value) {
return value == null ? null : pop();
}
List popList(int n) {
if (n == 0) return null;
List list = new List(n);
for (int i = n - 1; i >= 0; i--) {
list[i] = pop();
}
return list;
}
void push(Object node) {
if (node == null) throw "null not allowed.";
stack.addLast(node);
}
}