mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 16:31:07 +00:00
Use parser and scanner from package:front_end.
Originally reviewed as: Review-Url: https://codereview.chromium.org/2650413002 . Review-Url: https://codereview.chromium.org/2652203002 . Review-Url: https://codereview.chromium.org/2655843002 . Review-Url: https://codereview.chromium.org/2654433009 . Review-Url: https://codereview.chromium.org/2647343003 . Review-Url: https://codereview.chromium.org/2652663005 . Review-Url: https://codereview.chromium.org/2650813002 . Review-Url: https://codereview.chromium.org/2650803002 . Review-Url: https://codereview.chromium.org/2651843004 . Review-Url: https://codereview.chromium.org/2649923002 . Review-Url: https://codereview.chromium.org/2651563003 . Review-Url: https://codereview.chromium.org/2649123002 . Review-Url: https://codereview.chromium.org/2644843006 . Review-Url: https://codereview.chromium.org/2647043002 . Review-Url: https://codereview.chromium.org/2642903003 . Review-Url: https://codereview.chromium.org/2645513002 . Review-Url: https://codereview.chromium.org/2642663003 . Review-Url: https://codereview.chromium.org/2642713002 . Review-Url: https://codereview.chromium.org/2635473002 . Review-Url: https://codereview.chromium.org/2624373003 . Review-Url: https://codereview.chromium.org/2627723006 . Review-Url: https://codereview.chromium.org/2627093007 . Review-Url: https://codereview.chromium.org/2629543008 . Review-Url: https://codereview.chromium.org/2629543007 . Review-Url: https://codereview.chromium.org/2631503002 . Review-Url: https://codereview.chromium.org/2621153006 .
This commit is contained in:
parent
2a4bc2c7e5
commit
d0d27c1c38
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -75,3 +75,6 @@ editor/util/testing/mac/CodeLab.suite/Results
|
|||
editor/util/testing/mac/DartEditor.suite/Results
|
||||
editor/util/testing/mac/Samples.suite/Results
|
||||
.test-outcome.log
|
||||
/outline.dill
|
||||
/generated/
|
||||
/crash_logs/
|
||||
|
|
|
@ -28,7 +28,6 @@ compiler_unsupported:pkg/compiler/lib
|
|||
convert:third_party/pkg/convert/lib
|
||||
crypto:third_party/pkg/crypto/lib
|
||||
csslib:third_party/pkg/csslib/lib
|
||||
dart2js_incremental:pkg/dart2js_incremental/lib
|
||||
dart2js_info:third_party/pkg/dart2js_info/lib
|
||||
dart_messages:pkg/dart_messages/lib
|
||||
dart_style:third_party/pkg_tested/dart_style/lib
|
||||
|
@ -90,7 +89,8 @@ stack_trace:third_party/pkg/stack_trace/lib
|
|||
stream_channel:third_party/pkg/stream_channel/lib
|
||||
string_scanner:third_party/pkg/string_scanner/lib
|
||||
test:third_party/pkg/test/lib
|
||||
testing:third_party/testing/lib
|
||||
test_dart:tools/testing/dart
|
||||
testing:pkg/testing/lib
|
||||
test_reflective_loader:third_party/pkg/test_reflective_loader/lib
|
||||
typed_data:third_party/pkg/typed_data/lib
|
||||
typed_mock:pkg/typed_mock/lib
|
||||
|
|
|
@ -18,7 +18,7 @@ import 'elements/modelx.dart'
|
|||
import 'elements/visitor.dart' show ElementVisitor;
|
||||
import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
||||
import 'resolution/tree_elements.dart' show TreeElements;
|
||||
import 'tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import 'tree/tree.dart';
|
||||
import 'util/util.dart';
|
||||
import 'world.dart' show ClosedWorldRefiner;
|
||||
|
|
|
@ -17,7 +17,6 @@ import '../elements/elements.dart'
|
|||
FunctionElement,
|
||||
LocalFunctionElement,
|
||||
ResolvedAst;
|
||||
import '../enqueue.dart' show Enqueuer;
|
||||
import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
|
||||
import '../universe/world_impact.dart'
|
||||
show WorldImpact, WorldImpactBuilderImpl, WorldImpactVisitor;
|
||||
|
|
|
@ -30,6 +30,7 @@ import '../mirrors_used.dart';
|
|||
import '../options.dart' show CompilerOptions;
|
||||
import '../parser/element_listener.dart' show ScannerOptions;
|
||||
import '../parser/parser_task.dart';
|
||||
import '../scanner/scanner_task.dart';
|
||||
import '../patch_parser.dart';
|
||||
import '../resolution/resolution.dart';
|
||||
import '../tree/tree.dart' show Send, TypeAnnotation;
|
||||
|
@ -215,10 +216,12 @@ abstract class Resolution implements Frontend {
|
|||
/// A container of commonly used dependencies for tasks that involve parsing.
|
||||
abstract class ParsingContext {
|
||||
factory ParsingContext(DiagnosticReporter reporter, ParserTask parser,
|
||||
PatchParserTask patchParser, Backend backend) = _ParsingContext;
|
||||
ScannerTask scanner, PatchParserTask patchParser, Backend backend)
|
||||
= _ParsingContext;
|
||||
|
||||
DiagnosticReporter get reporter;
|
||||
ParserTask get parser;
|
||||
ScannerTask get scanner;
|
||||
PatchParserTask get patchParser;
|
||||
|
||||
/// Use [patchParser] directly instead.
|
||||
|
@ -236,10 +239,12 @@ abstract class ParsingContext {
|
|||
class _ParsingContext implements ParsingContext {
|
||||
final DiagnosticReporter reporter;
|
||||
final ParserTask parser;
|
||||
final ScannerTask scanner;
|
||||
final PatchParserTask patchParser;
|
||||
final Backend backend;
|
||||
|
||||
_ParsingContext(this.reporter, this.parser, this.patchParser, this.backend);
|
||||
_ParsingContext(this.reporter, this.parser, this.scanner, this.patchParser,
|
||||
this.backend);
|
||||
|
||||
@override
|
||||
measure(f()) => parser.measure(f);
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
library dart2js.common.work;
|
||||
|
||||
import '../common.dart';
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../elements/elements.dart' show AstElement;
|
||||
import '../enqueue.dart' show Enqueuer;
|
||||
import '../universe/world_impact.dart' show WorldImpact;
|
||||
|
||||
abstract class WorkItem {
|
||||
|
|
|
@ -1294,7 +1294,7 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
|||
Function compileArgument = (element) => definitions[element];
|
||||
Function compileConstant = handler.compileConstant;
|
||||
FunctionElement target = constructor.definingConstructor.implementation;
|
||||
Elements.addForwardingElementArgumentsToList<AstConstant>(constructor,
|
||||
Elements.addForwardingElementArgumentsToList(constructor,
|
||||
compiledArguments, target, compileArgument, compileConstant);
|
||||
CallStructure callStructure = new CallStructure(
|
||||
target.functionSignature.parameterCount, target.type.namedParameters);
|
||||
|
|
|
@ -66,9 +66,9 @@ import 'scanner/scanner_task.dart' show ScannerTask;
|
|||
import 'script.dart' show Script;
|
||||
import 'serialization/task.dart' show SerializationTask;
|
||||
import 'ssa/nodes.dart' show HInstruction;
|
||||
import 'tokens/token.dart' show StringToken, Token, TokenPair;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show StringToken, Token;
|
||||
import 'tokens/token_map.dart' show TokenMap;
|
||||
import 'tracer.dart' show Tracer;
|
||||
import 'tree/tree.dart' show Node, TypeAnnotation;
|
||||
import 'typechecker.dart' show TypeCheckerTask;
|
||||
import 'types/types.dart' show GlobalTypeInferenceTask;
|
||||
|
@ -80,7 +80,6 @@ import 'universe/world_impact.dart'
|
|||
show
|
||||
ImpactStrategy,
|
||||
WorldImpact,
|
||||
WorldImpactBuilder,
|
||||
WorldImpactBuilderImpl;
|
||||
import 'util/util.dart' show Link, Setlet;
|
||||
import 'world.dart' show ClosedWorld, ClosedWorldRefiner, ClosedWorldImpl;
|
||||
|
@ -266,7 +265,7 @@ abstract class Compiler implements LibraryLoaderListener {
|
|||
}
|
||||
|
||||
_parsingContext =
|
||||
new ParsingContext(reporter, parser, patchParser, backend);
|
||||
new ParsingContext(reporter, parser, scanner, patchParser, backend);
|
||||
|
||||
tasks.addAll(backend.tasks);
|
||||
}
|
||||
|
@ -1214,9 +1213,6 @@ class _CompilerCommonElements extends CommonElementsMixin {
|
|||
return _findLibraryMember(library, name, required: required);
|
||||
}
|
||||
|
||||
Element _findRequired(LibraryElement library, String name) =>
|
||||
_findLibraryMember(library, name);
|
||||
|
||||
Element _findLibraryMember(LibraryElement library, String name,
|
||||
{bool required: true}) {
|
||||
// If the script of the library is synthesized, the library does not exist
|
||||
|
@ -1398,6 +1394,9 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
|||
api.Diagnostic.CRASH);
|
||||
}
|
||||
|
||||
@override
|
||||
SourceSpan spanFromToken(Token token) => spanFromTokens(token, token);
|
||||
|
||||
SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) {
|
||||
if (begin == null || end == null) {
|
||||
// TODO(ahe): We can almost always do better. Often it is only
|
||||
|
@ -1546,10 +1545,6 @@ class CompilerDiagnosticReporter extends DiagnosticReporter {
|
|||
return node;
|
||||
} else if (node is Node) {
|
||||
return spanFromNode(node);
|
||||
} else if (node is TokenPair) {
|
||||
return spanFromTokens(node.begin, node.end);
|
||||
} else if (node is Token) {
|
||||
return spanFromTokens(node, node);
|
||||
} else if (node is HInstruction) {
|
||||
return spanFromHInstruction(node);
|
||||
} else if (node is Element) {
|
||||
|
@ -1715,7 +1710,6 @@ class CompilerResolution implements Resolution {
|
|||
MirrorUsageAnalyzerTask get mirrorUsageAnalyzerTask =>
|
||||
_compiler.mirrorUsageAnalyzerTask;
|
||||
|
||||
@override
|
||||
LibraryElement get coreLibrary => _compiler._commonElements.coreLibrary;
|
||||
|
||||
@override
|
||||
|
|
|
@ -122,7 +122,6 @@ Future<api.CompilationResult> compile(List<String> argv) {
|
|||
Uri resolutionOutput = currentDirectory.resolve('out.data');
|
||||
bool allowNativeExtensions = false;
|
||||
bool trustTypeAnnotations = false;
|
||||
bool trustJSInteropTypeAnnotations = false;
|
||||
bool checkedMode = false;
|
||||
List<String> hints = <String>[];
|
||||
bool verbose;
|
||||
|
@ -243,7 +242,6 @@ Future<api.CompilationResult> compile(List<String> argv) {
|
|||
}
|
||||
|
||||
void setTrustJSInteropTypeAnnotations(String argument) {
|
||||
trustJSInteropTypeAnnotations = true;
|
||||
implyCompilation(argument);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ import 'universe/world_impact.dart'
|
|||
show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
|
||||
import 'util/setlet.dart' show Setlet;
|
||||
import 'util/uri_extras.dart' as uri_extras;
|
||||
import 'util/util.dart' show Link, makeUnique;
|
||||
import 'util/util.dart' show makeUnique;
|
||||
|
||||
/// A "hunk" of the program that will be loaded whenever one of its [imports]
|
||||
/// are loaded.
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
library dart2js.diagnostic_listener;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../elements/elements.dart' show Element;
|
||||
import '../options.dart' show DiagnosticOptions;
|
||||
import 'messages.dart';
|
||||
|
@ -21,11 +22,16 @@ abstract class DiagnosticReporter {
|
|||
|
||||
/// Creates a [SourceSpan] for [node] in scope of the current element.
|
||||
///
|
||||
/// If [node] is a [Node] or [Token] we assert in checked mode that the
|
||||
/// corresponding tokens can be found within the tokens of the current
|
||||
/// element.
|
||||
/// If [node] is a [Node] we assert in checked mode that the corresponding
|
||||
/// tokens can be found within the tokens of the current element.
|
||||
SourceSpan spanFromSpannable(Spannable node);
|
||||
|
||||
/// Creates a [SourceSpan] for [token] in scope of the current element.
|
||||
///
|
||||
/// In checked mode we assert that the token can be found within the tokens
|
||||
/// of the current element.
|
||||
SourceSpan spanFromToken(Token token);
|
||||
|
||||
void reportErrorMessage(Spannable spannable, MessageKind messageKind,
|
||||
[Map arguments = const {}]) {
|
||||
reportError(createMessage(spannable, messageKind, arguments));
|
||||
|
|
|
@ -62,7 +62,8 @@
|
|||
|
||||
library dart2js.messages;
|
||||
|
||||
import '../tokens/token.dart' show ErrorToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show ErrorToken, Token;
|
||||
import 'generated/shared_messages.dart' as shared_messages;
|
||||
import 'invariant.dart' show invariant;
|
||||
import 'spannable.dart' show CURRENT_ELEMENT_SPANNABLE;
|
||||
|
@ -3090,7 +3091,9 @@ main() => r\"\"\"
|
|||
examples: const [
|
||||
"main(",
|
||||
"main(){",
|
||||
"main(){]}",
|
||||
"main(){[}",
|
||||
// TODO(ahe): https://github.com/dart-lang/sdk/issues/28495
|
||||
// "main(){]}",
|
||||
]),
|
||||
|
||||
MessageKind.UNTERMINATED_TOKEN: const MessageTemplate(
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
library dart2js.diagnostics.source_span;
|
||||
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../tree/tree.dart' show Node;
|
||||
import 'spannable.dart' show Spannable;
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ import '../ordered_typeset.dart' show OrderedTypeSet;
|
|||
import '../resolution/scope.dart' show Scope;
|
||||
import '../resolution/tree_elements.dart' show TreeElements;
|
||||
import '../script.dart';
|
||||
import '../tokens/token.dart'
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show Token, isUserDefinableOperator, isMinusOperator;
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/call_structure.dart';
|
||||
import '../util/characters.dart' show $_;
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart' show $_;
|
||||
import '../util/util.dart';
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'entities.dart';
|
||||
|
|
|
@ -20,8 +20,10 @@ import '../resolution/scope.dart'
|
|||
import '../resolution/tree_elements.dart' show TreeElements;
|
||||
import '../resolution/typedefs.dart' show TypedefCyclicVisitor;
|
||||
import '../script.dart';
|
||||
import '../tokens/token.dart' show ErrorToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show ErrorToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' as Tokens
|
||||
show EOF_TOKEN;
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart';
|
||||
import 'common.dart';
|
||||
|
@ -314,7 +316,6 @@ class ErroneousConstructorElementX extends ErroneousElementX
|
|||
@override
|
||||
bool isRedirectingGenerativeInternal;
|
||||
|
||||
@override
|
||||
void set isRedirectingGenerative(_) {
|
||||
throw new UnsupportedError("isRedirectingGenerative");
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ int _rotl32(int val, int shift) {
|
|||
// functions.
|
||||
abstract class _HashBase implements Hash {
|
||||
final int _chunkSizeInWords;
|
||||
final int _digestSizeInWords;
|
||||
final bool _bigEndianWords;
|
||||
final List<int> _currentChunk;
|
||||
final List<int> _h;
|
||||
|
@ -91,8 +90,7 @@ abstract class _HashBase implements Hash {
|
|||
: _pendingData = [],
|
||||
_currentChunk = new List(chunkSizeInWords),
|
||||
_h = new List(digestSizeInWords),
|
||||
_chunkSizeInWords = chunkSizeInWords,
|
||||
_digestSizeInWords = digestSizeInWords;
|
||||
_chunkSizeInWords = chunkSizeInWords;
|
||||
|
||||
// Update the hasher with more data.
|
||||
void add(List<int> data) {
|
||||
|
|
|
@ -102,7 +102,6 @@ StackTraceLines stackTrace({int offset: 1, int limit: null}) {
|
|||
rangeEnd: rangeEnd,
|
||||
filePrefix: stackTraceFilePrefix);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// A stack trace as a sequence of [StackTraceLine]s.
|
||||
|
|
|
@ -1215,7 +1215,6 @@ class ElementGraphBuilder extends ast.Visitor<TypeInformation>
|
|||
(element != null && element.isInstanceMember);
|
||||
}
|
||||
|
||||
@override
|
||||
TypeInformation handleSendSet(ast.SendSet node) {
|
||||
Element element = elements[node];
|
||||
if (!Elements.isUnresolved(element) && element.impliesType) {
|
||||
|
@ -2280,7 +2279,6 @@ class ElementGraphBuilder extends ast.Visitor<TypeInformation>
|
|||
return inferrer.registerAwait(node, futureType);
|
||||
}
|
||||
|
||||
@override
|
||||
TypeInformation handleTypeLiteralInvoke(ast.NodeList arguments) {
|
||||
// This is reached when users forget to put a `new` in front of a type
|
||||
// literal. The emitter will generate an actual call (even though it is
|
||||
|
|
|
@ -6,7 +6,6 @@ library type_graph_inferrer;
|
|||
|
||||
import 'dart:collection' show Queue;
|
||||
|
||||
import '../common.dart';
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../elements/elements.dart';
|
||||
import '../tree/tree.dart' as ast show Node;
|
||||
|
|
|
@ -12,7 +12,7 @@ import '../diagnostics/messages.dart' show MessageTemplate;
|
|||
import '../elements/elements.dart' show ResolvedAst, ResolvedAstKind;
|
||||
import '../js/js.dart' as js;
|
||||
import '../js/js_source_mapping.dart';
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../tree/tree.dart' show Node;
|
||||
import 'source_file.dart';
|
||||
import 'source_information.dart';
|
||||
|
|
|
@ -129,7 +129,6 @@ abstract class ReferenceCountedAstNode implements Node {
|
|||
/// This is used when generated code needs to be represented as a string,
|
||||
/// for example by the lazy emitter or when generating code generators.
|
||||
class UnparsedNode extends DeferredString implements AstContainer {
|
||||
@override
|
||||
final Node tree;
|
||||
final Compiler _compiler;
|
||||
final bool _protectForEval;
|
||||
|
|
|
@ -905,7 +905,8 @@ class JavaScriptBackend extends Backend {
|
|||
if (elements.isEmpty) return false;
|
||||
return elements.any((element) {
|
||||
return selector.applies(element) &&
|
||||
(mask == null || mask.canHit(element, selector, _closedWorld));
|
||||
(mask == null ||
|
||||
mask.canHit(element as MemberElement, selector, _closedWorld));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -206,8 +206,6 @@ class BackendHelpers {
|
|||
// TODO(johnniwinther): Split into _findHelperFunction and _findHelperClass
|
||||
// and add a check that the element has the expected kind.
|
||||
Element _findHelper(String name) => _find(jsHelperLibrary, name);
|
||||
FunctionElement _findHelperFunction(String name) =>
|
||||
_find(jsHelperLibrary, name);
|
||||
Element _findAsyncHelper(String name) => _find(asyncLibrary, name);
|
||||
Element _findInterceptor(String name) => _find(interceptorsLibrary, name);
|
||||
Element _find(LibraryElement library, String name) {
|
||||
|
|
|
@ -12,7 +12,6 @@ import '../elements/elements.dart' show ClassElement, Element;
|
|||
import '../universe/selector.dart';
|
||||
import '../util/enumset.dart';
|
||||
import 'backend_helpers.dart';
|
||||
import 'constant_system_javascript.dart';
|
||||
import 'js_backend.dart';
|
||||
|
||||
/// Backend specific features required by a backend impact.
|
||||
|
|
|
@ -6,7 +6,6 @@ import '../compiler.dart' show Compiler;
|
|||
import '../constants/values.dart';
|
||||
import '../elements/resolution_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../enqueue.dart' show Enqueuer;
|
||||
import '../universe/use.dart' show StaticUse;
|
||||
import '../universe/world_impact.dart'
|
||||
show WorldImpact, StagedWorldImpactBuilder;
|
||||
|
|
|
@ -17,7 +17,6 @@ import '../constants/values.dart'
|
|||
NullConstantValue,
|
||||
StringConstantValue,
|
||||
TypeConstantValue;
|
||||
import '../elements/resolution_types.dart' show ResolutionDartType;
|
||||
import '../elements/resolution_types.dart' show ResolutionInterfaceType;
|
||||
import '../elements/elements.dart'
|
||||
show ClassElement, FieldElement, LibraryElement, VariableElement;
|
||||
|
|
|
@ -317,25 +317,20 @@ class _ConstructorBodyNamingScope {
|
|||
|
||||
int get numberOfConstructors => _constructors.length;
|
||||
|
||||
_ConstructorBodyNamingScope _superScope;
|
||||
|
||||
_ConstructorBodyNamingScope.rootScope(ClassElement cls)
|
||||
: _superScope = null,
|
||||
_startIndex = 0,
|
||||
: _startIndex = 0,
|
||||
_constructors = cls.constructors.toList(growable: false);
|
||||
|
||||
_ConstructorBodyNamingScope.forClass(
|
||||
ClassElement cls, _ConstructorBodyNamingScope superScope)
|
||||
: _superScope = superScope,
|
||||
_startIndex = superScope._startIndex + superScope.numberOfConstructors,
|
||||
: _startIndex = superScope._startIndex + superScope.numberOfConstructors,
|
||||
_constructors = cls.constructors.toList(growable: false);
|
||||
|
||||
// Mixin Applications have constructors but we never generate code for them,
|
||||
// so they do not count in the inheritance chain.
|
||||
_ConstructorBodyNamingScope.forMixinApplication(
|
||||
ClassElement cls, _ConstructorBodyNamingScope superScope)
|
||||
: _superScope = superScope,
|
||||
_startIndex = superScope._startIndex + superScope.numberOfConstructors,
|
||||
: _startIndex = superScope._startIndex + superScope.numberOfConstructors,
|
||||
_constructors = const [];
|
||||
|
||||
factory _ConstructorBodyNamingScope(ClassElement cls,
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:js_runtime/shared/embedded_names.dart' show JsGetName;
|
|||
import '../closure.dart';
|
||||
import '../common.dart';
|
||||
import '../common/names.dart' show Identifiers, Selectors;
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../constants/values.dart';
|
||||
import '../core_types.dart' show CommonElements;
|
||||
import '../elements/resolution_types.dart';
|
||||
|
@ -24,7 +23,7 @@ import '../tree/tree.dart';
|
|||
import '../universe/call_structure.dart' show CallStructure;
|
||||
import '../universe/selector.dart' show Selector, SelectorKind;
|
||||
import '../universe/world_builder.dart' show CodegenWorldBuilder;
|
||||
import '../util/characters.dart';
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart';
|
||||
import '../util/util.dart';
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'backend.dart';
|
||||
|
|
|
@ -589,7 +589,6 @@ class _RuntimeTypes implements RuntimeTypes {
|
|||
|
||||
class _RuntimeTypesEncoder implements RuntimeTypesEncoder {
|
||||
final Compiler compiler;
|
||||
@override
|
||||
final TypeRepresentationGenerator representationGenerator;
|
||||
|
||||
_RuntimeTypesEncoder(Compiler compiler)
|
||||
|
|
|
@ -8,12 +8,10 @@ import '../constants/expressions.dart';
|
|||
import '../constants/values.dart';
|
||||
import '../elements/resolution_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../enqueue.dart' show Enqueuer;
|
||||
import '../js/js.dart' as jsAst;
|
||||
import '../js_emitter/js_emitter.dart'
|
||||
show CodeEmitterTask, MetadataCollector, Placeholder;
|
||||
import '../universe/call_structure.dart' show CallStructure;
|
||||
import '../universe/use.dart' show StaticUse;
|
||||
import '../universe/world_impact.dart';
|
||||
import '../util/util.dart';
|
||||
import 'backend.dart';
|
||||
|
@ -101,7 +99,6 @@ class TypeVariableHandler {
|
|||
// Do not process classes twice.
|
||||
if (_typeVariables.containsKey(cls)) return;
|
||||
|
||||
ResolutionInterfaceType typeVariableType = _typeVariableClass.thisType;
|
||||
List<jsAst.Expression> constants = <jsAst.Expression>[];
|
||||
|
||||
for (ResolutionTypeVariableType currentTypeVariable in cls.typeVariables) {
|
||||
|
@ -111,8 +108,6 @@ class TypeVariableHandler {
|
|||
_metadataCollector.reifyType(typeVariableElement.bound);
|
||||
ConstantValue boundValue = new SyntheticConstantValue(
|
||||
SyntheticConstantKind.TYPEVARIABLE_REFERENCE, boundIndex);
|
||||
ConstantExpression boundExpression =
|
||||
new SyntheticConstantExpression(boundValue);
|
||||
ConstantExpression constant = new ConstructedConstantExpression(
|
||||
_typeVariableConstructor.enclosingClass.thisType,
|
||||
_typeVariableConstructor,
|
||||
|
|
|
@ -9,7 +9,8 @@ import '../../js/js.dart' as jsAst;
|
|||
import '../../js/js.dart' show js;
|
||||
import '../../js_backend/js_backend.dart' show GetterName, SetterName;
|
||||
import '../../universe/selector.dart' show Selector;
|
||||
import '../../util/characters.dart' show $$, $A, $HASH, $Z, $a, $z;
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart'
|
||||
show $$, $A, $HASH, $Z, $a, $z;
|
||||
import '../../world.dart' show ClosedWorld;
|
||||
import '../js_emitter.dart' hide Emitter, EmitterFactory;
|
||||
import '../model.dart';
|
||||
|
|
|
@ -281,7 +281,6 @@ class Collector {
|
|||
}
|
||||
|
||||
void computeNeededStaticNonFinalFields() {
|
||||
JavaScriptConstantCompiler handler = backend.constants;
|
||||
addToOutputUnit(Element element) {
|
||||
List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent(
|
||||
compiler.deferredLoadTask.outputUnitForElement(element),
|
||||
|
|
|
@ -183,7 +183,7 @@ class ProgramBuilder {
|
|||
List<js.TokenFinalizer> finalizers = [_task.metadataCollector];
|
||||
if (backend.namer is js.TokenFinalizer) {
|
||||
var namingFinalizer = backend.namer;
|
||||
finalizers.add(namingFinalizer);
|
||||
finalizers.add(namingFinalizer as js.TokenFinalizer);
|
||||
}
|
||||
|
||||
return new Program(fragments, holders, _buildLoadMap(), _symbolsMap,
|
||||
|
|
|
@ -1037,11 +1037,8 @@ class KernelVisitor extends Object
|
|||
}
|
||||
ir.SwitchCase irCase = casesIterator.current;
|
||||
List<ir.Statement> statements = <ir.Statement>[];
|
||||
bool hasVariableDeclaration = false;
|
||||
for (Statement statement in caseNode.statements.nodes) {
|
||||
if (buildStatement(statement, statements)) {
|
||||
hasVariableDeclaration = true;
|
||||
}
|
||||
buildStatement(statement, statements);
|
||||
}
|
||||
if (statements.isEmpty || fallsThrough(statements.last)) {
|
||||
if (isLastCase) {
|
||||
|
@ -2116,7 +2113,6 @@ class KernelVisitor extends Object
|
|||
// [body] must be `null`.
|
||||
} else if (function.isConstructor) {
|
||||
// TODO(johnniwinther): Clean this up pending kernel issue #28.
|
||||
ConstructorElement constructor = function;
|
||||
if (bodyNode == null || bodyNode.asEmptyStatement() != null) {
|
||||
body = new ir.EmptyStatement();
|
||||
} else {
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
// 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.
|
||||
|
||||
import 'dart:collection' show Queue;
|
||||
|
||||
import '../common.dart';
|
||||
import '../common/backend_api.dart' show ForeignResolver;
|
||||
import '../common/resolution.dart' show Resolution;
|
||||
|
@ -17,8 +15,10 @@ import '../elements/resolution_types.dart';
|
|||
import '../js_backend/backend_helpers.dart' show BackendHelpers;
|
||||
import '../js_backend/js_backend.dart';
|
||||
import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
|
||||
import '../tokens/token.dart' show BeginGroupToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show BeginGroupToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' as Tokens
|
||||
show EOF_TOKEN;
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/use.dart' show StaticUse, TypeUse;
|
||||
import '../universe/world_impact.dart'
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
|
||||
import '../common.dart';
|
||||
import '../parser/element_listener.dart' show ElementListener;
|
||||
import '../tokens/token.dart' show BeginGroupToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show STRING_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show BeginGroupToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner/token_constants.dart' as Tokens
|
||||
show STRING_TOKEN;
|
||||
|
||||
void checkAllowedLibrary(ElementListener listener, Token token) {
|
||||
if (listener.scannerOptions.canUseNative) return;
|
||||
listener.reportError(token, MessageKind.NATIVE_NOT_SUPPORTED);
|
||||
listener.reportErrorFromToken(token, MessageKind.NATIVE_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
Token handleNativeBlockToSkip(ElementListener listener, Token token) {
|
||||
|
|
|
@ -9,7 +9,8 @@ import 'elements/resolution_types.dart';
|
|||
import 'diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
|
||||
import 'elements/elements.dart' show ClassElement;
|
||||
import 'util/util.dart' show Link, LinkBuilder;
|
||||
import 'util/util_implementation.dart' show LinkEntry;
|
||||
import 'package:front_end/src/fasta/util/link_implementation.dart'
|
||||
show LinkEntry;
|
||||
|
||||
/**
|
||||
* An ordered set of the supertypes of a class. The supertypes of a class are
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) 2011, 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 dart2js.parser.classes;
|
||||
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'listener.dart' show Listener;
|
||||
import 'partial_parser.dart' show PartialParser;
|
||||
|
||||
class ClassElementParser extends PartialParser {
|
||||
ClassElementParser(Listener listener) : super(listener);
|
||||
|
||||
Token parseClassBody(Token token) => fullParseClassBody(token);
|
||||
}
|
|
@ -9,10 +9,17 @@ import '../common/backend_api.dart' show Backend;
|
|||
import '../common/tasks.dart' show CompilerTask, Measurer;
|
||||
import '../elements/elements.dart' show CompilationUnitElement;
|
||||
import '../id_generator.dart';
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import 'element_listener.dart' show ElementListener, ScannerOptions;
|
||||
import 'listener.dart' show ParserError;
|
||||
import 'partial_parser.dart' show PartialParser;
|
||||
import 'package:front_end/src/fasta/parser.dart'
|
||||
show Listener, ParserError, TopLevelParser;
|
||||
|
||||
class PartialParser extends TopLevelParser {
|
||||
PartialParser(Listener listener)
|
||||
: super(listener);
|
||||
|
||||
Token parseFormalParameters(Token token) => skipFormalParameters(token);
|
||||
}
|
||||
|
||||
class DietParserTask extends CompilerTask {
|
||||
final IdGenerator _idGenerator;
|
||||
|
|
|
@ -22,14 +22,16 @@ import '../elements/modelx.dart'
|
|||
import '../id_generator.dart';
|
||||
import '../native/native.dart' as native;
|
||||
import '../string_validator.dart' show StringValidator;
|
||||
import '../tokens/keyword.dart' show Keyword;
|
||||
import '../tokens/precedence_constants.dart' as Precedence show BAD_INPUT_INFO;
|
||||
import '../tokens/token.dart'
|
||||
show BeginGroupToken, ErrorToken, KeywordToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show Keyword, BeginGroupToken, ErrorToken, KeywordToken, StringToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' as Tokens
|
||||
show EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence show
|
||||
BAD_INPUT_INFO, IDENTIFIER_INFO;
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart' show Link, LinkBuilder;
|
||||
import 'listener.dart' show closeBraceFor, Listener, ParserError, VERBOSE;
|
||||
import 'package:front_end/src/fasta/parser.dart'
|
||||
show ErrorKind, Listener, ParserError, optional;
|
||||
import 'partial_elements.dart'
|
||||
show
|
||||
PartialClassElement,
|
||||
|
@ -39,6 +41,8 @@ import 'partial_elements.dart'
|
|||
PartialMetadataAnnotation,
|
||||
PartialTypedefElement;
|
||||
|
||||
const bool VERBOSE = false;
|
||||
|
||||
/// Options used for scanning.
|
||||
///
|
||||
/// Use this to conditionally support special tokens.
|
||||
|
@ -82,6 +86,10 @@ class ElementListener extends Listener {
|
|||
|
||||
bool suppressParseErrors = false;
|
||||
|
||||
/// Set to true each time we parse a native function body. It is reset in
|
||||
/// [handleInvalidFunctionBody] which is called immediately after.
|
||||
bool lastErrorWasNativeFunctionBody = false;
|
||||
|
||||
ElementListener(this.scannerOptions, DiagnosticReporter reporter,
|
||||
this.compilationUnitElement, this.idGenerator)
|
||||
: this.reporter = reporter,
|
||||
|
@ -121,12 +129,14 @@ class ElementListener extends Listener {
|
|||
library.entryCompilationUnit == compilationUnitElement;
|
||||
}
|
||||
|
||||
@override
|
||||
void endLibraryName(Token libraryKeyword, Token semicolon) {
|
||||
Expression name = popNode();
|
||||
addLibraryTag(new LibraryName(
|
||||
libraryKeyword, name, popMetadata(compilationUnitElement)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
|
||||
Token semicolon) {
|
||||
NodeList combinators = popNode();
|
||||
|
@ -142,11 +152,13 @@ class ElementListener extends Listener {
|
|||
isDeferred: isDeferred));
|
||||
}
|
||||
|
||||
@override
|
||||
void endDottedName(int count, Token token) {
|
||||
NodeList identifiers = makeNodeList(count, null, null, '.');
|
||||
pushNode(new DottedName(token, identifiers));
|
||||
}
|
||||
|
||||
@override
|
||||
void endConditionalUris(int count) {
|
||||
if (count == 0) {
|
||||
pushNode(null);
|
||||
|
@ -155,6 +167,7 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endConditionalUri(Token ifToken, Token equalSign) {
|
||||
StringNode uri = popNode();
|
||||
LiteralString conditionValue = (equalSign != null) ? popNode() : null;
|
||||
|
@ -162,6 +175,7 @@ class ElementListener extends Listener {
|
|||
pushNode(new ConditionalUri(ifToken, identifier, conditionValue, uri));
|
||||
}
|
||||
|
||||
@override
|
||||
void endEnum(Token enumKeyword, Token endBrace, int count) {
|
||||
NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
|
||||
Identifier name = popNode();
|
||||
|
@ -173,6 +187,7 @@ class ElementListener extends Listener {
|
|||
rejectBuiltInIdentifier(name);
|
||||
}
|
||||
|
||||
@override
|
||||
void endExport(Token exportKeyword, Token semicolon) {
|
||||
NodeList combinators = popNode();
|
||||
NodeList conditionalUris = popNode();
|
||||
|
@ -181,6 +196,7 @@ class ElementListener extends Listener {
|
|||
popMetadata(compilationUnitElement)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endCombinators(int count) {
|
||||
if (0 == count) {
|
||||
pushNode(null);
|
||||
|
@ -189,8 +205,10 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endHide(Token hideKeyword) => pushCombinator(hideKeyword);
|
||||
|
||||
@override
|
||||
void endShow(Token showKeyword) => pushCombinator(showKeyword);
|
||||
|
||||
void pushCombinator(Token keywordToken) {
|
||||
|
@ -198,20 +216,24 @@ class ElementListener extends Listener {
|
|||
pushNode(new Combinator(identifiers, keywordToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endIdentifierList(int count) {
|
||||
pushNode(makeNodeList(count, null, null, ","));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTypeList(int count) {
|
||||
pushNode(makeNodeList(count, null, null, ","));
|
||||
}
|
||||
|
||||
@override
|
||||
void endPart(Token partKeyword, Token semicolon) {
|
||||
StringNode uri = popLiteralString();
|
||||
addLibraryTag(
|
||||
new Part(partKeyword, uri, popMetadata(compilationUnitElement)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endPartOf(Token partKeyword, Token semicolon) {
|
||||
Expression name = popNode();
|
||||
addPartOfTag(
|
||||
|
@ -222,6 +244,7 @@ class ElementListener extends Listener {
|
|||
compilationUnitElement.setPartOf(tag, reporter);
|
||||
}
|
||||
|
||||
@override
|
||||
void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
|
||||
if (periodBeforeName != null) {
|
||||
popNode(); // Discard name.
|
||||
|
@ -230,14 +253,17 @@ class ElementListener extends Listener {
|
|||
pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelDeclaration(Token token) {
|
||||
if (!metadata.isEmpty) {
|
||||
MetadataAnnotationX first = metadata.first;
|
||||
recoverableError(first.beginToken, 'Metadata not supported here.');
|
||||
recoverableError(reporter.spanFromToken(first.beginToken),
|
||||
'Metadata not supported here.');
|
||||
metadata.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endClassDeclaration(int interfacesCount, Token beginToken,
|
||||
Token extendsKeyword, Token implementsKeyword, Token endToken) {
|
||||
makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces
|
||||
|
@ -260,6 +286,7 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
|
||||
popNode(); // TODO(karlklose): do not throw away typeVariables.
|
||||
Identifier name = popNode();
|
||||
|
@ -269,6 +296,7 @@ class ElementListener extends Listener {
|
|||
rejectBuiltInIdentifier(name);
|
||||
}
|
||||
|
||||
@override
|
||||
void endNamedMixinApplication(
|
||||
Token classKeyword, Token implementsKeyword, Token endToken) {
|
||||
NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
|
||||
|
@ -292,16 +320,19 @@ class ElementListener extends Listener {
|
|||
rejectBuiltInIdentifier(name);
|
||||
}
|
||||
|
||||
@override
|
||||
void endMixinApplication() {
|
||||
NodeList mixins = popNode();
|
||||
TypeAnnotation superclass = popNode();
|
||||
pushNode(new MixinApplication(superclass, mixins));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleVoidKeyword(Token token) {
|
||||
pushNode(new TypeAnnotation(new Identifier(token), null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
|
||||
bool hasParseError = currentMemberHasParseError;
|
||||
memberErrors = memberErrors.tail;
|
||||
|
@ -315,6 +346,7 @@ class ElementListener extends Listener {
|
|||
pushElement(element);
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelFields(int count, Token beginToken, Token endToken) {
|
||||
bool hasParseError = currentMemberHasParseError;
|
||||
memberErrors = memberErrors.tail;
|
||||
|
@ -351,20 +383,24 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleIdentifier(Token token) {
|
||||
pushNode(new Identifier(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleQualified(Token period) {
|
||||
Identifier last = popNode();
|
||||
Expression first = popNode();
|
||||
pushNode(new Send(first, last));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoType(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endTypeVariable(Token token, Token extendsOrSuper) {
|
||||
TypeAnnotation bound = popNode();
|
||||
Identifier name = popNode();
|
||||
|
@ -372,37 +408,45 @@ class ElementListener extends Listener {
|
|||
rejectBuiltInIdentifier(name);
|
||||
}
|
||||
|
||||
@override
|
||||
void endTypeVariables(int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, endToken, ','));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoTypeVariables(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endTypeArguments(int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, endToken, ','));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoTypeArguments(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endType(Token beginToken, Token endToken) {
|
||||
NodeList typeArguments = popNode();
|
||||
Expression typeName = popNode();
|
||||
pushNode(new TypeAnnotation(typeName, typeArguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleParenthesizedExpression(BeginGroupToken token) {
|
||||
Expression expression = popNode();
|
||||
pushNode(new ParenthesizedExpression(expression, token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleModifier(Token token) {
|
||||
pushNode(new Identifier(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleModifiers(int count) {
|
||||
if (count == 0) {
|
||||
pushNode(Modifiers.EMPTY);
|
||||
|
@ -412,29 +456,234 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
Token expected(String string, Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else if (identical(';', string)) {
|
||||
// When a semicolon is missing, it often leads to an error on the
|
||||
// following line. So we try to find the token preceding the semicolon
|
||||
// and report that something is missing *after* it.
|
||||
Token preceding = findPrecedingToken(token);
|
||||
if (preceding == token) {
|
||||
reportError(
|
||||
token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string});
|
||||
} else {
|
||||
reportError(
|
||||
preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string});
|
||||
}
|
||||
return token;
|
||||
@override
|
||||
Token handleUnrecoverableError(Token token, ErrorKind kind, Map arguments) {
|
||||
Token next = handleError(token, kind, arguments);
|
||||
if (next == null &&
|
||||
kind != ErrorKind.UnterminatedComment &&
|
||||
kind != ErrorKind.UnterminatedString) {
|
||||
throw new ParserError.fromTokens(token, token, kind, arguments);
|
||||
} else {
|
||||
reportFatalError(
|
||||
token,
|
||||
MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
|
||||
.message({'token': string}, true).toString());
|
||||
return next;
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleRecoverableError(Token token, ErrorKind kind, Map arguments) {
|
||||
handleError(token, kind, arguments);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidExpression(Token token) {
|
||||
pushNode(new ErrorExpression(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidFunctionBody(Token token) {
|
||||
lastErrorWasNativeFunctionBody = false;
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidTypeReference(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
Token handleError(Token token, ErrorKind kind, Map arguments) {
|
||||
MessageKind errorCode;
|
||||
|
||||
switch (kind) {
|
||||
case ErrorKind.ExpectedButGot:
|
||||
String expected = arguments["expected"];
|
||||
if (identical(";", expected)) {
|
||||
// When a semicolon is missing, it often leads to an error on the
|
||||
// following line. So we try to find the token preceding the semicolon
|
||||
// and report that something is missing *after* it.
|
||||
Token preceding = findPrecedingToken(token);
|
||||
if (preceding == token) {
|
||||
reportErrorFromToken(
|
||||
token, MessageKind.MISSING_TOKEN_BEFORE_THIS,
|
||||
{'token': expected});
|
||||
} else {
|
||||
reportErrorFromToken(
|
||||
preceding, MessageKind.MISSING_TOKEN_AFTER_THIS,
|
||||
{'token': expected});
|
||||
}
|
||||
return token;
|
||||
} else {
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
|
||||
.message({'token': expected}, true).toString());
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedIdentifier:
|
||||
if (token is KeywordToken) {
|
||||
reportErrorFromToken(token,
|
||||
MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
|
||||
{'keyword': token.value});
|
||||
} else if (token is ErrorToken) {
|
||||
// TODO(ahe): This is dead code.
|
||||
return synthesizeIdentifier(token);
|
||||
} else {
|
||||
reportFatalError(reporter.spanFromToken(token),
|
||||
"Expected identifier, but got '${token.value}'.");
|
||||
}
|
||||
return token;
|
||||
|
||||
case ErrorKind.ExpectedType:
|
||||
reportFatalError(reporter.spanFromToken(token),
|
||||
"Expected a type, but got '${token.value}'.");
|
||||
return null;
|
||||
|
||||
case ErrorKind.ExpectedExpression:
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
"Expected an expression, but got '${token.value}'.");
|
||||
return null;
|
||||
|
||||
case ErrorKind.UnexpectedToken:
|
||||
String message = "Unexpected token '${token.value}'.";
|
||||
if (token.info == Precedence.BAD_INPUT_INFO) {
|
||||
message = token.value;
|
||||
}
|
||||
reportFatalError(reporter.spanFromToken(token), message);
|
||||
return null;
|
||||
|
||||
case ErrorKind.ExpectedBlockToSkip:
|
||||
if (optional("native", token)) {
|
||||
return native.handleNativeBlockToSkip(this, token);
|
||||
} else {
|
||||
errorCode = MessageKind.BODY_EXPECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedFunctionBody:
|
||||
if (optional("native", token)) {
|
||||
lastErrorWasNativeFunctionBody = true;
|
||||
return native.handleNativeFunctionBody(this, token);
|
||||
} else {
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
"Expected a function body, but got '${token.value}'.");
|
||||
}
|
||||
return null;
|
||||
|
||||
case ErrorKind.ExpectedClassBodyToSkip:
|
||||
case ErrorKind.ExpectedClassBody:
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
"Expected a class body, but got '${token.value}'.");
|
||||
return null;
|
||||
|
||||
case ErrorKind.ExpectedDeclaration:
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
"Expected a declaration, but got '${token.value}'.");
|
||||
return null;
|
||||
|
||||
case ErrorKind.UnmatchedToken:
|
||||
reportErrorFromToken(token, MessageKind.UNMATCHED_TOKEN, arguments);
|
||||
Token next = token.next;
|
||||
while (next is ErrorToken) {
|
||||
next = next.next;
|
||||
}
|
||||
return next;
|
||||
|
||||
case ErrorKind.EmptyNamedParameterList:
|
||||
errorCode = MessageKind.EMPTY_NAMED_PARAMETER_LIST;
|
||||
break;
|
||||
|
||||
case ErrorKind.EmptyOptionalParameterList:
|
||||
errorCode = MessageKind.EMPTY_OPTIONAL_PARAMETER_LIST;
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedBody:
|
||||
errorCode = MessageKind.BODY_EXPECTED;
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedHexDigit:
|
||||
errorCode = MessageKind.HEX_DIGIT_EXPECTED;
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedOpenParens:
|
||||
errorCode = MessageKind.GENERIC;
|
||||
arguments = {"text": "Expected '('."};
|
||||
break;
|
||||
|
||||
case ErrorKind.ExpectedString:
|
||||
reportFatalError(
|
||||
reporter.spanFromToken(token),
|
||||
"Expected a String, but got '${token.value}'.");
|
||||
return null;
|
||||
|
||||
case ErrorKind.ExtraneousModifier:
|
||||
errorCode = MessageKind.EXTRANEOUS_MODIFIER;
|
||||
break;
|
||||
|
||||
case ErrorKind.ExtraneousModifierReplace:
|
||||
errorCode = MessageKind.EXTRANEOUS_MODIFIER_REPLACE;
|
||||
break;
|
||||
|
||||
case ErrorKind.InvalidAwaitFor:
|
||||
errorCode = MessageKind.INVALID_AWAIT_FOR;
|
||||
break;
|
||||
|
||||
case ErrorKind.InvalidInputCharacter:
|
||||
errorCode = MessageKind.BAD_INPUT_CHARACTER;
|
||||
break;
|
||||
|
||||
case ErrorKind.InvalidSyncModifier:
|
||||
errorCode = MessageKind.INVALID_SYNC_MODIFIER;
|
||||
break;
|
||||
|
||||
case ErrorKind.InvalidVoid:
|
||||
errorCode = MessageKind.VOID_NOT_ALLOWED;
|
||||
break;
|
||||
|
||||
case ErrorKind.MalformedStringLiteral:
|
||||
errorCode = MessageKind.MALFORMED_STRING_LITERAL;
|
||||
break;
|
||||
|
||||
case ErrorKind.MissingExponent:
|
||||
errorCode = MessageKind.EXPONENT_MISSING;
|
||||
break;
|
||||
|
||||
case ErrorKind.PositionalParameterWithEquals:
|
||||
errorCode = MessageKind.POSITIONAL_PARAMETER_WITH_EQUALS;
|
||||
break;
|
||||
|
||||
case ErrorKind.RequiredParameterWithDefault:
|
||||
errorCode = MessageKind.REQUIRED_PARAMETER_WITH_DEFAULT;
|
||||
break;
|
||||
|
||||
case ErrorKind.UnmatchedToken:
|
||||
errorCode = MessageKind.UNMATCHED_TOKEN;
|
||||
break;
|
||||
|
||||
case ErrorKind.UnsupportedPrefixPlus:
|
||||
errorCode = MessageKind.UNSUPPORTED_PREFIX_PLUS;
|
||||
break;
|
||||
|
||||
case ErrorKind.UnterminatedComment:
|
||||
errorCode = MessageKind.UNTERMINATED_COMMENT;
|
||||
break;
|
||||
|
||||
case ErrorKind.UnterminatedString:
|
||||
errorCode = MessageKind.UNTERMINATED_STRING;
|
||||
break;
|
||||
|
||||
case ErrorKind.UnterminatedToken:
|
||||
errorCode = MessageKind.UNTERMINATED_TOKEN;
|
||||
break;
|
||||
|
||||
case ErrorKind.Unspecified:
|
||||
errorCode = MessageKind.GENERIC;
|
||||
break;
|
||||
}
|
||||
SourceSpan span = reporter.spanFromToken(token);
|
||||
reportError(span, errorCode, arguments);
|
||||
}
|
||||
|
||||
/// Finds the preceding token via the begin token of the last AST node pushed
|
||||
|
@ -494,113 +743,13 @@ class ElementListener extends Listener {
|
|||
return null;
|
||||
}
|
||||
|
||||
Token expectedIdentifier(Token token) {
|
||||
if (token is KeywordToken) {
|
||||
reportError(token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
|
||||
{'keyword': token.value});
|
||||
} else if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
return synthesizeIdentifier(token);
|
||||
} else {
|
||||
reportFatalError(token, "Expected identifier, but got '${token.value}'.");
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token expectedType(Token token) {
|
||||
pushNode(null);
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
return synthesizeIdentifier(token);
|
||||
} else {
|
||||
reportFatalError(token, "Expected a type, but got '${token.value}'.");
|
||||
return skipToEof(token);
|
||||
}
|
||||
}
|
||||
|
||||
Token expectedExpression(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
pushNode(new ErrorExpression(token));
|
||||
return token.next;
|
||||
} else {
|
||||
reportFatalError(
|
||||
token, "Expected an expression, but got '${token.value}'.");
|
||||
pushNode(null);
|
||||
return skipToEof(token);
|
||||
}
|
||||
}
|
||||
|
||||
Token unexpected(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
String message = "Unexpected token '${token.value}'.";
|
||||
if (token.info == Precedence.BAD_INPUT_INFO) {
|
||||
message = token.value;
|
||||
}
|
||||
reportFatalError(token, message);
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
Token expectedBlockToSkip(Token token) {
|
||||
if (identical(token.stringValue, 'native')) {
|
||||
return native.handleNativeBlockToSkip(this, token);
|
||||
} else {
|
||||
return unexpected(token);
|
||||
}
|
||||
}
|
||||
|
||||
Token expectedFunctionBody(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
String printString = token.value;
|
||||
reportFatalError(
|
||||
token, "Expected a function body, but got '$printString'.");
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
Token expectedClassBody(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
reportFatalError(
|
||||
token, "Expected a class body, but got '${token.value}'.");
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
Token expectedClassBodyToSkip(Token token) {
|
||||
return unexpected(token);
|
||||
}
|
||||
|
||||
Token expectedDeclaration(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
reportFatalError(
|
||||
token, "Expected a declaration, but got '${token.value}'.");
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
Token unmatched(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
String begin = token.value;
|
||||
String end = closeBraceFor(begin);
|
||||
reportError(
|
||||
token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
|
||||
}
|
||||
Token next = token.next;
|
||||
while (next is ErrorToken) {
|
||||
next = next.next;
|
||||
}
|
||||
return next;
|
||||
/// Finds the preceding token via the begin token of the last AST node pushed
|
||||
/// on the [nodes] stack.
|
||||
Token synthesizeIdentifier(Token token) {
|
||||
Token synthesizedToken = new StringToken.fromString(
|
||||
Precedence.IDENTIFIER_INFO, '?', token.charOffset);
|
||||
synthesizedToken.next = token.next;
|
||||
return synthesizedToken;
|
||||
}
|
||||
|
||||
void recoverableError(Spannable node, String message) {
|
||||
|
@ -663,6 +812,7 @@ class ElementListener extends Listener {
|
|||
return new NodeList(beginToken, poppedNodes, endToken, delimiter);
|
||||
}
|
||||
|
||||
@override
|
||||
void beginLiteralString(Token token) {
|
||||
String source = token.value;
|
||||
StringQuoting quoting = StringValidator.quotingFromString(source);
|
||||
|
@ -672,12 +822,14 @@ class ElementListener extends Listener {
|
|||
pushNode(new LiteralString(token, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleStringPart(Token token) {
|
||||
// Just push an unvalidated token now, and replace it when we know the
|
||||
// end of the interpolation.
|
||||
pushNode(new LiteralString(token, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endLiteralString(int count) {
|
||||
StringQuoting quoting = popQuoting();
|
||||
|
||||
|
@ -711,6 +863,7 @@ class ElementListener extends Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleStringJuxtaposition(int stringCount) {
|
||||
assert(stringCount != 0);
|
||||
Expression accumulator = popNode();
|
||||
|
@ -723,14 +876,17 @@ class ElementListener extends Listener {
|
|||
pushNode(accumulator);
|
||||
}
|
||||
|
||||
@override
|
||||
void beginMember(Token token) {
|
||||
memberErrors = memberErrors.prepend(false);
|
||||
}
|
||||
|
||||
@override
|
||||
void beginTopLevelMember(Token token) {
|
||||
beginMember(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void endMember() {
|
||||
memberErrors = memberErrors.tail;
|
||||
}
|
||||
|
@ -740,11 +896,12 @@ class ElementListener extends Listener {
|
|||
void reportFatalError(Spannable spannable, String message) {
|
||||
reportError(spannable, MessageKind.GENERIC, {'text': message});
|
||||
// Some parse errors are infeasible to recover from, so we throw an error.
|
||||
throw new ParserError(message);
|
||||
SourceSpan span = reporter.spanFromSpannable(spannable);
|
||||
throw new ParserError(
|
||||
span.begin, span.end, ErrorKind.Unspecified, {'text': message});
|
||||
}
|
||||
|
||||
@override
|
||||
void reportErrorHelper(Spannable spannable, MessageKind errorCode,
|
||||
void reportError(Spannable spannable, MessageKind errorCode,
|
||||
[Map arguments = const {}]) {
|
||||
if (currentMemberHasParseError) return; // Error already reported.
|
||||
if (suppressParseErrors) return;
|
||||
|
@ -753,4 +910,9 @@ class ElementListener extends Listener {
|
|||
}
|
||||
reporter.reportErrorMessage(spannable, errorCode, arguments);
|
||||
}
|
||||
|
||||
void reportErrorFromToken(Token token, MessageKind errorCode,
|
||||
[Map arguments = const {}]) {
|
||||
reportError(reporter.spanFromToken(token), errorCode, arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import '../common.dart';
|
|||
import '../elements/elements.dart' show Element, ElementKind, Elements;
|
||||
import '../elements/modelx.dart'
|
||||
show ClassElementX, ElementX, FieldElementX, VariableList;
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../tree/tree.dart';
|
||||
import 'element_listener.dart' show ScannerOptions;
|
||||
import 'node_listener.dart' show NodeListener;
|
||||
|
@ -67,6 +67,7 @@ class MemberListener extends NodeListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endMethod(Token getOrSet, Token beginToken, Token endToken) {
|
||||
super.endMethod(getOrSet, beginToken, endToken);
|
||||
FunctionExpression method = popNode();
|
||||
|
@ -76,7 +77,7 @@ class MemberListener extends NodeListener {
|
|||
Element memberElement;
|
||||
if (isConstructor) {
|
||||
if (getOrSet != null) {
|
||||
recoverableError(getOrSet, 'illegal modifier');
|
||||
recoverableError(reporter.spanFromToken(getOrSet), 'illegal modifier');
|
||||
}
|
||||
memberElement = new PartialConstructorElement(name, beginToken, endToken,
|
||||
ElementKind.GENERATIVE_CONSTRUCTOR, method.modifiers, enclosingClass);
|
||||
|
@ -88,6 +89,7 @@ class MemberListener extends NodeListener {
|
|||
addMember(memberElement);
|
||||
}
|
||||
|
||||
@override
|
||||
void endFactoryMethod(Token beginToken, Token endToken) {
|
||||
super.endFactoryMethod(beginToken, endToken);
|
||||
FunctionExpression method = popNode();
|
||||
|
@ -112,6 +114,7 @@ class MemberListener extends NodeListener {
|
|||
addMember(memberElement);
|
||||
}
|
||||
|
||||
@override
|
||||
void endFields(int count, Token beginToken, Token endToken) {
|
||||
bool hasParseError = memberErrors.head;
|
||||
super.endFields(count, beginToken, endToken);
|
||||
|
@ -127,12 +130,14 @@ class MemberListener extends NodeListener {
|
|||
enclosingClass, buildFieldElement, beginToken, endToken, hasParseError);
|
||||
}
|
||||
|
||||
void endInitializer(Token assignmentOperator) {
|
||||
@override
|
||||
void endFieldInitializer(Token assignmentOperator) {
|
||||
pushNode(null); // Super expects an expression, but
|
||||
// ClassElementParser just skips expressions.
|
||||
super.endInitializer(assignmentOperator);
|
||||
super.endFieldInitializer(assignmentOperator);
|
||||
}
|
||||
|
||||
@override
|
||||
void endInitializers(int count, Token beginToken, Token endToken) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
@ -146,6 +151,7 @@ class MemberListener extends NodeListener {
|
|||
enclosingClass.addMember(memberElement, reporter);
|
||||
}
|
||||
|
||||
@override
|
||||
void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
|
||||
super.endMetadata(beginToken, periodBeforeName, endToken);
|
||||
pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
|
||||
|
|
|
@ -6,27 +6,30 @@ library dart2js.parser.node_listener;
|
|||
|
||||
import '../common.dart';
|
||||
import '../elements/elements.dart' show CompilationUnitElement;
|
||||
import '../native/native.dart' as native;
|
||||
import '../tokens/precedence_constants.dart' as Precedence show INDEX_INFO;
|
||||
import '../tokens/token.dart' show ErrorToken, StringToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence show
|
||||
INDEX_INFO;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show
|
||||
StringToken, Token;
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart' show Link;
|
||||
import 'element_listener.dart' show ElementListener, ScannerOptions;
|
||||
import 'partial_elements.dart' show PartialFunctionElement;
|
||||
|
||||
class NodeListener extends ElementListener {
|
||||
NodeListener(ScannerOptions scannerOptions, DiagnosticReporter reporter,
|
||||
CompilationUnitElement element)
|
||||
: super(scannerOptions, reporter, element, null);
|
||||
|
||||
@override
|
||||
void addLibraryTag(LibraryTag tag) {
|
||||
pushNode(tag);
|
||||
}
|
||||
|
||||
@override
|
||||
void addPartOfTag(PartOf tag) {
|
||||
pushNode(tag);
|
||||
}
|
||||
|
||||
@override
|
||||
void endLibraryName(Token libraryKeyword, Token semicolon) {
|
||||
Expression name = popNode();
|
||||
pushNode(new LibraryName(
|
||||
|
@ -37,6 +40,7 @@ class NodeListener extends ElementListener {
|
|||
null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
|
||||
Token semicolon) {
|
||||
NodeList combinators = popNode();
|
||||
|
@ -55,6 +59,7 @@ class NodeListener extends ElementListener {
|
|||
isDeferred: deferredKeyword != null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endExport(Token exportKeyword, Token semicolon) {
|
||||
NodeList combinators = popNode();
|
||||
NodeList conditionalUris = popNode();
|
||||
|
@ -69,6 +74,7 @@ class NodeListener extends ElementListener {
|
|||
null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endPart(Token partKeyword, Token semicolon) {
|
||||
StringNode uri = popLiteralString();
|
||||
pushNode(new Part(
|
||||
|
@ -79,6 +85,7 @@ class NodeListener extends ElementListener {
|
|||
null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endPartOf(Token partKeyword, Token semicolon) {
|
||||
Expression name = popNode(); // name
|
||||
pushNode(new PartOf(
|
||||
|
@ -89,6 +96,7 @@ class NodeListener extends ElementListener {
|
|||
null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endClassDeclaration(int interfacesCount, Token beginToken,
|
||||
Token extendsKeyword, Token implementsKeyword, Token endToken) {
|
||||
NodeList body = popNode();
|
||||
|
@ -102,6 +110,7 @@ class NodeListener extends ElementListener {
|
|||
interfaces, beginToken, extendsKeyword, body, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelDeclaration(Token token) {
|
||||
// TODO(sigmund): consider moving metadata into each declaration
|
||||
// element instead.
|
||||
|
@ -111,10 +120,12 @@ class NodeListener extends ElementListener {
|
|||
super.endTopLevelDeclaration(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void endCompilationUnit(int count, Token token) {
|
||||
pushNode(makeNodeList(count, null, null, '\n'));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
|
||||
NodeList formals = popNode();
|
||||
NodeList typeParameters = popNode();
|
||||
|
@ -124,6 +135,7 @@ class NodeListener extends ElementListener {
|
|||
returnType, name, typeParameters, formals, typedefKeyword, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endNamedMixinApplication(
|
||||
Token classKeyword, Token implementsKeyword, Token endToken) {
|
||||
NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
|
||||
|
@ -135,16 +147,19 @@ class NodeListener extends ElementListener {
|
|||
mixinApplication, interfaces, classKeyword, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endEnum(Token enumKeyword, Token endBrace, int count) {
|
||||
NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
|
||||
Identifier name = popNode();
|
||||
pushNode(new Enum(enumKeyword, name, names));
|
||||
}
|
||||
|
||||
@override
|
||||
void endClassBody(int memberCount, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(memberCount, beginToken, endToken, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelFields(int count, Token beginToken, Token endToken) {
|
||||
NodeList variables = makeNodeList(count, null, endToken, ",");
|
||||
TypeAnnotation type = popNode();
|
||||
|
@ -152,6 +167,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new VariableDefinitions(type, modifiers, variables));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
|
||||
Statement body = popNode();
|
||||
AsyncModifier asyncModifier = popNode();
|
||||
|
@ -164,6 +180,7 @@ class NodeListener extends ElementListener {
|
|||
modifiers, null, getOrSet, asyncModifier));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFormalParameter(Token thisKeyword) {
|
||||
Expression name = popNode();
|
||||
if (thisKeyword != null) {
|
||||
|
@ -181,22 +198,27 @@ class NodeListener extends ElementListener {
|
|||
metadata, type, modifiers, new NodeList.singleton(name)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFormalParameters(int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, endToken, ","));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoFormalParameters(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endArguments(int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, endToken, ","));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoArguments(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endConstructorReference(
|
||||
Token start, Token periodBeforeName, Token endToken) {
|
||||
Identifier name = null;
|
||||
|
@ -228,74 +250,61 @@ class NodeListener extends ElementListener {
|
|||
pushNode(constructor);
|
||||
}
|
||||
|
||||
@override
|
||||
void endRedirectingFactoryBody(Token beginToken, Token endToken) {
|
||||
pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
|
||||
}
|
||||
|
||||
@override
|
||||
void endReturnStatement(
|
||||
bool hasExpression, Token beginToken, Token endToken) {
|
||||
Expression expression = hasExpression ? popNode() : null;
|
||||
pushNode(new Return(beginToken, endToken, expression));
|
||||
}
|
||||
|
||||
@override
|
||||
void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
|
||||
Expression expression = popNode();
|
||||
pushNode(new Yield(yieldToken, starToken, expression, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endExpressionStatement(Token token) {
|
||||
pushNode(new ExpressionStatement(popNode(), token));
|
||||
}
|
||||
|
||||
void handleOnError(Token token, var errorInformation) {
|
||||
reporter.internalError(token, "'${token.value}': ${errorInformation}");
|
||||
}
|
||||
|
||||
Token expectedFunctionBody(Token token) {
|
||||
if (identical(token.stringValue, 'native')) {
|
||||
return native.handleNativeFunctionBody(this, token);
|
||||
} else if (token is ErrorToken) {
|
||||
pushNode(null);
|
||||
reportErrorToken(token);
|
||||
} else {
|
||||
reportFatalError(
|
||||
token, "Expected a function body, but got '${token.value}'.");
|
||||
}
|
||||
return skipToEof(token);
|
||||
}
|
||||
|
||||
Token expectedClassBody(Token token) {
|
||||
if (token is ErrorToken) {
|
||||
reportErrorToken(token);
|
||||
return skipToEof(token);
|
||||
} else {
|
||||
reportFatalError(
|
||||
token, "Expected a class body, but got '${token.value}'.");
|
||||
return skipToEof(token);
|
||||
}
|
||||
reporter.internalError(reporter.spanFromToken(token),
|
||||
"'${token.value}': ${errorInformation}");
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralInt(Token token) {
|
||||
pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralDouble(Token token) {
|
||||
pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralBool(Token token) {
|
||||
pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralNull(Token token) {
|
||||
pushNode(new LiteralNull(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void endLiteralSymbol(Token hashToken, int identifierCount) {
|
||||
NodeList identifiers = makeNodeList(identifierCount, null, null, '.');
|
||||
pushNode(new LiteralSymbol(hashToken, identifiers));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleBinaryExpression(Token token) {
|
||||
Node argument = popNode();
|
||||
Node receiver = popNode();
|
||||
|
@ -307,7 +316,8 @@ class NodeListener extends ElementListener {
|
|||
if (argumentSend == null) {
|
||||
// TODO(ahe): The parser should diagnose this problem, not
|
||||
// this listener.
|
||||
reportFatalError(argument, 'Expected an identifier.');
|
||||
reportFatalError(reporter.spanFromSpannable(argument),
|
||||
"Expected an identifier.");
|
||||
}
|
||||
if (argumentSend.receiver != null) internalError(node: argument);
|
||||
if (argument is SendSet) internalError(node: argument);
|
||||
|
@ -319,23 +329,27 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Send(receiver, new Operator(token), arguments));
|
||||
}
|
||||
if (identical(tokenString, '===')) {
|
||||
reporter.reportErrorMessage(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ,
|
||||
{'lhs': receiver, 'rhs': argument});
|
||||
reporter.reportErrorMessage(reporter.spanFromToken(token),
|
||||
MessageKind.UNSUPPORTED_EQ_EQ_EQ, {'lhs': receiver, 'rhs': argument});
|
||||
}
|
||||
if (identical(tokenString, '!==')) {
|
||||
reporter.reportErrorMessage(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ,
|
||||
reporter.reportErrorMessage(reporter.spanFromToken(token),
|
||||
MessageKind.UNSUPPORTED_BANG_EQ_EQ,
|
||||
{'lhs': receiver, 'rhs': argument});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void beginCascade(Token token) {
|
||||
pushNode(new CascadeReceiver(popNode(), token));
|
||||
}
|
||||
|
||||
@override
|
||||
void endCascade() {
|
||||
pushNode(new Cascade(popNode()));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAsOperator(Token operator, Token endToken) {
|
||||
TypeAnnotation type = popNode();
|
||||
Expression expression = popNode();
|
||||
|
@ -343,6 +357,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Send(expression, new Operator(operator), arguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAssignmentExpression(Token token) {
|
||||
Node arg = popNode();
|
||||
Node node = popNode();
|
||||
|
@ -367,9 +382,10 @@ class NodeListener extends ElementListener {
|
|||
void reportNotAssignable(Node node) {
|
||||
// TODO(ahe): The parser should diagnose this problem, not this
|
||||
// listener.
|
||||
reportFatalError(node, 'Not assignable.');
|
||||
reportFatalError(reporter.spanFromSpannable(node), "Not assignable.");
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConditionalExpression(Token question, Token colon) {
|
||||
Node elseExpression = popNode();
|
||||
Node thenExpression = popNode();
|
||||
|
@ -378,6 +394,7 @@ class NodeListener extends ElementListener {
|
|||
condition, thenExpression, elseExpression, question, colon));
|
||||
}
|
||||
|
||||
@override
|
||||
void endSend(Token token) {
|
||||
NodeList arguments = popNode();
|
||||
NodeList typeArguments = popNode();
|
||||
|
@ -386,6 +403,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Send(null, selector, arguments, typeArguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFunctionBody(int count, Token beginToken, Token endToken) {
|
||||
if (count == 0 && beginToken == null) {
|
||||
pushNode(new EmptyStatement(endToken));
|
||||
|
@ -394,6 +412,7 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAsyncModifier(Token asyncToken, Token starToken) {
|
||||
if (asyncToken != null) {
|
||||
pushNode(new AsyncModifier(asyncToken, starToken));
|
||||
|
@ -402,14 +421,17 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
void skippedFunctionBody(Token token) {
|
||||
@override
|
||||
void handleFunctionBodySkipped(Token token) {
|
||||
pushNode(new Block(new NodeList.empty()));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoFunctionBody(Token token) {
|
||||
pushNode(new EmptyStatement(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFunction(Token getOrSet, Token endToken) {
|
||||
Statement body = popNode();
|
||||
AsyncModifier asyncModifier = popNode();
|
||||
|
@ -424,10 +446,12 @@ class NodeListener extends ElementListener {
|
|||
modifiers, initializers, getOrSet, asyncModifier));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFunctionDeclaration(Token endToken) {
|
||||
pushNode(new FunctionDeclaration(popNode()));
|
||||
}
|
||||
|
||||
@override
|
||||
void endVariablesDeclaration(int count, Token endToken) {
|
||||
// TODO(ahe): Pick one name for this concept, either
|
||||
// VariablesDeclaration or VariableDefinitions.
|
||||
|
@ -437,7 +461,8 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new VariableDefinitions(type, modifiers, variables));
|
||||
}
|
||||
|
||||
void endInitializer(Token assignmentOperator) {
|
||||
@override
|
||||
void endVariableInitializer(Token assignmentOperator) {
|
||||
Expression initializer = popNode();
|
||||
NodeList arguments =
|
||||
initializer == null ? null : new NodeList.singleton(initializer);
|
||||
|
@ -446,6 +471,12 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new SendSet(null, name, op, arguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFieldInitializer(Token assignmentOperator) {
|
||||
endVariableInitializer(assignmentOperator);
|
||||
}
|
||||
|
||||
@override
|
||||
void endIfStatement(Token ifToken, Token elseToken) {
|
||||
Statement elsePart = (elseToken == null) ? null : popNode();
|
||||
Statement thenPart = popNode();
|
||||
|
@ -453,6 +484,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endForStatement(
|
||||
int updateExpressionCount, Token beginToken, Token endToken) {
|
||||
Statement body = popNode();
|
||||
|
@ -462,10 +494,12 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new For(initializer, condition, updates, body, beginToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoExpression(Token token) {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endDoWhileStatement(
|
||||
Token doKeyword, Token whileKeyword, Token endToken) {
|
||||
Expression condition = popNode();
|
||||
|
@ -473,42 +507,51 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endWhileStatement(Token whileKeyword, Token endToken) {
|
||||
Statement body = popNode();
|
||||
Expression condition = popNode();
|
||||
pushNode(new While(condition, body, whileKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void endBlock(int count, Token beginToken, Token endToken) {
|
||||
pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endThrowExpression(Token throwToken, Token endToken) {
|
||||
Expression expression = popNode();
|
||||
pushNode(new Throw(expression, throwToken, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endAwaitExpression(Token awaitToken, Token endToken) {
|
||||
Expression expression = popNode();
|
||||
pushNode(new Await(awaitToken, expression));
|
||||
}
|
||||
|
||||
@override
|
||||
void endRethrowStatement(Token throwToken, Token endToken) {
|
||||
pushNode(new Rethrow(throwToken, endToken));
|
||||
if (identical(throwToken.stringValue, 'throw')) {
|
||||
reporter.reportErrorMessage(
|
||||
throwToken, MessageKind.MISSING_EXPRESSION_IN_THROW);
|
||||
reporter.spanFromToken(throwToken),
|
||||
MessageKind.MISSING_EXPRESSION_IN_THROW);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleUnaryPrefixExpression(Token token) {
|
||||
pushNode(new Send.prefix(popNode(), new Operator(token)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleSuperExpression(Token token) {
|
||||
pushNode(new Identifier(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleThisExpression(Token token) {
|
||||
pushNode(new Identifier(token));
|
||||
}
|
||||
|
@ -536,22 +579,27 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleUnaryPostfixAssignmentExpression(Token token) {
|
||||
handleUnaryAssignmentExpression(token, false);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleUnaryPrefixAssignmentExpression(Token token) {
|
||||
handleUnaryAssignmentExpression(token, true);
|
||||
}
|
||||
|
||||
@override
|
||||
void endInitializers(int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, null, ','));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNoInitializers() {
|
||||
pushNode(null);
|
||||
}
|
||||
|
||||
@override
|
||||
void endMember() {
|
||||
// TODO(sigmund): consider moving metadata into each declaration
|
||||
// element instead.
|
||||
|
@ -561,6 +609,7 @@ class NodeListener extends ElementListener {
|
|||
super.endMember();
|
||||
}
|
||||
|
||||
@override
|
||||
void endFields(int count, Token beginToken, Token endToken) {
|
||||
NodeList variables = makeNodeList(count, null, endToken, ",");
|
||||
TypeAnnotation type = popNode();
|
||||
|
@ -568,6 +617,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new VariableDefinitions(type, modifiers, variables));
|
||||
}
|
||||
|
||||
@override
|
||||
void endMethod(Token getOrSet, Token beginToken, Token endToken) {
|
||||
Statement body = popNode();
|
||||
AsyncModifier asyncModifier = popNode();
|
||||
|
@ -581,6 +631,7 @@ class NodeListener extends ElementListener {
|
|||
returnType, modifiers, initializers, getOrSet, asyncModifier));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralMap(
|
||||
int count, Token beginToken, Token constKeyword, Token endToken) {
|
||||
NodeList entries = makeNodeList(count, beginToken, endToken, ',');
|
||||
|
@ -588,18 +639,21 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new LiteralMap(typeArguments, entries, constKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void endLiteralMapEntry(Token colon, Token endToken) {
|
||||
Expression value = popNode();
|
||||
Expression key = popNode();
|
||||
pushNode(new LiteralMapEntry(key, colon, value));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLiteralList(
|
||||
int count, Token beginToken, Token constKeyword, Token endToken) {
|
||||
NodeList elements = makeNodeList(count, beginToken, endToken, ',');
|
||||
pushNode(new LiteralList(popNode(), elements, constKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleIndexedExpression(
|
||||
Token openSquareBracket, Token closeSquareBracket) {
|
||||
NodeList arguments =
|
||||
|
@ -611,38 +665,45 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Send(receiver, selector, arguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNewExpression(Token token) {
|
||||
NodeList arguments = popNode();
|
||||
Node name = popNode();
|
||||
pushNode(new NewExpression(token, new Send(null, name, arguments)));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleConstExpression(Token token) {
|
||||
// [token] carries the 'const' information.
|
||||
handleNewExpression(token);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleOperator(Token token) {
|
||||
pushNode(new Operator(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleOperatorName(Token operatorKeyword, Token token) {
|
||||
Operator op = new Operator(token);
|
||||
pushNode(new Send(new Identifier(operatorKeyword), op, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleNamedArgument(Token colon) {
|
||||
Expression expression = popNode();
|
||||
Identifier name = popNode();
|
||||
pushNode(new NamedArgument(name, colon, expression));
|
||||
}
|
||||
|
||||
@override
|
||||
void endOptionalFormalParameters(
|
||||
int count, Token beginToken, Token endToken) {
|
||||
pushNode(makeNodeList(count, beginToken, endToken, ','));
|
||||
}
|
||||
|
||||
void handleFunctionTypedFormalParameter(Token endToken) {
|
||||
@override
|
||||
void endFunctionTypedFormalParameter(Token endToken) {
|
||||
NodeList formals = popNode();
|
||||
NodeList typeVariables = popNode();
|
||||
Identifier name = popNode();
|
||||
|
@ -652,6 +713,7 @@ class NodeListener extends ElementListener {
|
|||
returnType, Modifiers.EMPTY, null, null, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleValuedFormalParameter(Token equals, Token token) {
|
||||
Expression defaultValue = popNode();
|
||||
Expression parameterName = popNode();
|
||||
|
@ -659,6 +721,7 @@ class NodeListener extends ElementListener {
|
|||
new NodeList.singleton(defaultValue)));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
|
||||
Block finallyBlock = null;
|
||||
if (finallyKeyword != null) {
|
||||
|
@ -670,10 +733,12 @@ class NodeListener extends ElementListener {
|
|||
tryBlock, catchBlocks, finallyBlock, tryKeyword, finallyKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleCaseMatch(Token caseKeyword, Token colon) {
|
||||
pushNode(new CaseMatch(caseKeyword, popNode(), colon));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleCatchBlock(Token onKeyword, Token catchKeyword) {
|
||||
Block block = popNode();
|
||||
NodeList formals = catchKeyword != null ? popNode() : null;
|
||||
|
@ -681,12 +746,14 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void endSwitchStatement(Token switchKeyword, Token endToken) {
|
||||
NodeList cases = popNode();
|
||||
ParenthesizedExpression expression = popNode();
|
||||
pushNode(new SwitchStatement(expression, cases, switchKeyword));
|
||||
}
|
||||
|
||||
@override
|
||||
void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
|
||||
Link<Node> caseNodes = const Link<Node>();
|
||||
while (caseCount > 0) {
|
||||
|
@ -697,6 +764,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new NodeList(beginToken, caseNodes, endToken, null));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleSwitchCase(int labelCount, int caseCount, Token defaultKeyword,
|
||||
int statementCount, Token firstToken, Token endToken) {
|
||||
NodeList statements = makeNodeList(statementCount, null, null, null);
|
||||
|
@ -706,6 +774,7 @@ class NodeListener extends ElementListener {
|
|||
new SwitchCase(labelsAndCases, defaultKeyword, statements, firstToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleBreakStatement(
|
||||
bool hasTarget, Token breakKeyword, Token endToken) {
|
||||
Identifier target = null;
|
||||
|
@ -715,6 +784,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new BreakStatement(target, breakKeyword, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleContinueStatement(
|
||||
bool hasTarget, Token continueKeyword, Token endToken) {
|
||||
Identifier target = null;
|
||||
|
@ -724,10 +794,12 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new ContinueStatement(target, continueKeyword, endToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleEmptyStatement(Token token) {
|
||||
pushNode(new EmptyStatement(token));
|
||||
}
|
||||
|
||||
@override
|
||||
void endFactoryMethod(Token beginToken, Token endToken) {
|
||||
super.endFactoryMethod(beginToken, endToken);
|
||||
Statement body = popNode();
|
||||
|
@ -758,6 +830,7 @@ class NodeListener extends ElementListener {
|
|||
name, null, formals, body, null, modifiers, null, null, asyncModifier));
|
||||
}
|
||||
|
||||
@override
|
||||
void endForIn(
|
||||
Token awaitToken, Token forToken, Token inKeyword, Token endToken) {
|
||||
Statement body = popNode();
|
||||
|
@ -772,6 +845,7 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endMetadataStar(int count, bool forParameter) {
|
||||
if (0 == count) {
|
||||
pushNode(null);
|
||||
|
@ -780,6 +854,7 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
|
||||
NodeList arguments = popNode();
|
||||
if (arguments == null) {
|
||||
|
@ -816,6 +891,7 @@ class NodeListener extends ElementListener {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void handleAssertStatement(
|
||||
Token assertKeyword, Token commaToken, Token semicolonToken) {
|
||||
Node message;
|
||||
|
@ -827,6 +903,7 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Assert(assertKeyword, condition, message, semicolonToken));
|
||||
}
|
||||
|
||||
@override
|
||||
void endUnnamedFunction(Token token) {
|
||||
Statement body = popNode();
|
||||
AsyncModifier asyncModifier = popNode();
|
||||
|
@ -836,6 +913,7 @@ class NodeListener extends ElementListener {
|
|||
Modifiers.EMPTY, null, null, asyncModifier));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleIsOperator(Token operator, Token not, Token endToken) {
|
||||
TypeAnnotation type = popNode();
|
||||
Expression expression = popNode();
|
||||
|
@ -850,21 +928,32 @@ class NodeListener extends ElementListener {
|
|||
pushNode(new Send(expression, new Operator(operator), arguments));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleLabel(Token colon) {
|
||||
Identifier name = popNode();
|
||||
pushNode(new Label(name, colon));
|
||||
}
|
||||
|
||||
@override
|
||||
void endLabeledStatement(int labelCount) {
|
||||
Statement statement = popNode();
|
||||
NodeList labels = makeNodeList(labelCount, null, null, null);
|
||||
pushNode(new LabeledStatement(labels, statement));
|
||||
}
|
||||
|
||||
@override
|
||||
void log(message) {
|
||||
reporter.log(message);
|
||||
}
|
||||
|
||||
@override
|
||||
void handleInvalidFunctionBody(Token token) {
|
||||
if (!lastErrorWasNativeFunctionBody) {
|
||||
pushNode(null);
|
||||
}
|
||||
lastErrorWasNativeFunctionBody = false;
|
||||
}
|
||||
|
||||
void internalError({Token token, Node node}) {
|
||||
// TODO(ahe): This should call reporter.internalError.
|
||||
Spannable spannable = (token == null) ? node : token;
|
||||
|
|
|
@ -8,12 +8,11 @@ import '../common.dart';
|
|||
import '../common/tasks.dart' show CompilerTask;
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../elements/modelx.dart' show ElementX;
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../tree/tree.dart' show Node;
|
||||
import 'element_listener.dart' show ScannerOptions;
|
||||
import 'listener.dart' show ParserError;
|
||||
import 'package:front_end/src/fasta/parser.dart' show Parser, ParserError;
|
||||
import 'node_listener.dart' show NodeListener;
|
||||
import 'parser.dart' show Parser;
|
||||
|
||||
class ParserTask extends CompilerTask {
|
||||
final Compiler compiler;
|
||||
|
@ -36,7 +35,8 @@ class ParserTask extends CompilerTask {
|
|||
try {
|
||||
parser.parseUnit(token);
|
||||
} on ParserError catch (_) {
|
||||
assert(invariant(token, compiler.compilationFailed));
|
||||
assert(invariant(compiler.reporter.spanFromToken(token),
|
||||
compiler.compilationFailed));
|
||||
return listener.makeNodeList(0, null, null, '\n');
|
||||
}
|
||||
Node result = listener.popNode();
|
||||
|
|
|
@ -31,14 +31,20 @@ import '../elements/modelx.dart'
|
|||
TypedefElementX,
|
||||
VariableList;
|
||||
import '../elements/visitor.dart' show ElementVisitor;
|
||||
import '../tokens/token.dart' show Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
|
||||
import '../tree/tree.dart';
|
||||
import 'class_element_parser.dart' show ClassElementParser;
|
||||
import 'listener.dart' show ParserError;
|
||||
import 'package:front_end/src/fasta/parser.dart'
|
||||
show ClassMemberParser, Listener, Parser, ParserError;
|
||||
import 'member_listener.dart' show MemberListener;
|
||||
import 'node_listener.dart' show NodeListener;
|
||||
import 'parser.dart' show Parser;
|
||||
|
||||
class ClassElementParser extends ClassMemberParser {
|
||||
ClassElementParser(Listener listener)
|
||||
: super(listener);
|
||||
|
||||
Token parseFormalParameters(Token token) => skipFormalParameters(token);
|
||||
}
|
||||
|
||||
abstract class PartialElement implements DeclarationSite {
|
||||
Token beginToken;
|
||||
|
@ -379,8 +385,9 @@ class PartialClassElement extends ClassElementX with PartialElement {
|
|||
Token token = parser.parseTopLevelDeclaration(beginToken);
|
||||
assert(identical(token, endToken.next));
|
||||
cachedNode = listener.popNode();
|
||||
assert(invariant(beginToken, listener.nodes.isEmpty,
|
||||
message: "Non-empty listener stack: ${listener.nodes}"));
|
||||
assert(invariant(reporter.spanFromToken(beginToken),
|
||||
listener.nodes.isEmpty,
|
||||
message: "Non-empty listener stack: ${listener.nodes}"));
|
||||
} on ParserError {
|
||||
// TODO(ahe): Often, a ParserError is thrown while parsing the class
|
||||
// body. This means that the stack actually contains most of the
|
||||
|
@ -443,7 +450,7 @@ Node parse(ParsingContext parsing, ElementX element, PartialElement partial,
|
|||
doParse(new Parser(listener));
|
||||
} on ParserError catch (e) {
|
||||
partial.hasParseError = true;
|
||||
return new ErrorNode(element.position, e.reason);
|
||||
return new ErrorNode(element.position, e.kind, e.arguments);
|
||||
}
|
||||
Node node = listener.popNode();
|
||||
assert(listener.nodes.isEmpty);
|
||||
|
|
|
@ -134,14 +134,14 @@ import 'id_generator.dart';
|
|||
import 'js_backend/js_backend.dart' show JavaScriptBackend;
|
||||
import 'library_loader.dart' show LibraryLoader;
|
||||
import 'parser/element_listener.dart' show ElementListener;
|
||||
import 'parser/listener.dart' show Listener, ParserError;
|
||||
import 'package:front_end/src/fasta/parser.dart'
|
||||
show Listener, Parser, ParserError;
|
||||
import 'parser/member_listener.dart' show MemberListener;
|
||||
import 'parser/parser.dart' show Parser;
|
||||
import 'parser/partial_elements.dart' show PartialClassElement;
|
||||
import 'parser/partial_parser.dart' show PartialParser;
|
||||
import 'scanner/scanner.dart' show Scanner;
|
||||
import 'parser/partial_elements.dart'
|
||||
show ClassElementParser, PartialClassElement;
|
||||
import 'script.dart';
|
||||
import 'tokens/token.dart' show StringToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show StringToken, Token;
|
||||
import 'parser/diet_parser_task.dart' show PartialParser;
|
||||
|
||||
class PatchParserTask extends CompilerTask {
|
||||
final String name = "Patching Parser";
|
||||
|
@ -178,7 +178,7 @@ class PatchParserTask extends CompilerTask {
|
|||
measure(() {
|
||||
// TODO(johnniwinther): Test that parts and exports are handled correctly.
|
||||
Script script = compilationUnit.script;
|
||||
Token tokens = new Scanner(script.file).tokenize();
|
||||
Token tokens = compiler.scanner.scanFile(script.file);
|
||||
Listener patchListener = new PatchElementListener(
|
||||
compiler, compilationUnit, compiler.idGenerator);
|
||||
try {
|
||||
|
@ -199,7 +199,7 @@ class PatchParserTask extends CompilerTask {
|
|||
|
||||
measure(() => reporter.withCurrentElement(cls, () {
|
||||
MemberListener listener = new PatchMemberListener(compiler, cls);
|
||||
Parser parser = new PatchClassElementParser(listener);
|
||||
Parser parser = new ClassElementParser(listener);
|
||||
try {
|
||||
Token token = parser.parseTopLevelDeclaration(cls.beginToken);
|
||||
assert(identical(token, cls.endToken.next));
|
||||
|
@ -244,16 +244,6 @@ class PatchMemberListener extends MemberListener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Partial parser for patch files that also handles the members of class
|
||||
* declarations.
|
||||
*/
|
||||
class PatchClassElementParser extends PartialParser {
|
||||
PatchClassElementParser(Listener listener) : super(listener);
|
||||
|
||||
Token parseClassBody(Token token) => fullParseClassBody(token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of [ElementListener] for parsing patch files.
|
||||
*/
|
||||
|
|
|
@ -9,10 +9,9 @@ import '../core_types.dart' show CommonElements;
|
|||
import '../elements/resolution_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../elements/modelx.dart';
|
||||
import '../tokens/keyword.dart' show Keyword;
|
||||
import '../tokens/precedence.dart';
|
||||
import '../tokens/precedence_constants.dart' as Precedence;
|
||||
import '../tokens/token.dart';
|
||||
import 'package:front_end/src/fasta/scanner.dart';
|
||||
import 'package:front_end/src/fasta/scanner/precedence.dart';
|
||||
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence;
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart';
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import '../elements/modelx.dart'
|
|||
VariableElementX,
|
||||
VariableList;
|
||||
import '../options.dart';
|
||||
import '../tokens/token.dart' show isUserDefinableOperator;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show isUserDefinableOperator;
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/call_structure.dart' show CallStructure;
|
||||
import '../universe/feature.dart' show Feature;
|
||||
|
@ -2841,7 +2841,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
} else if (member.isFunction) {
|
||||
// `a = b`, `a++` or `a += b` where `a` is a function.
|
||||
MethodElement method = member;
|
||||
ErroneousElement error = reportAndCreateErroneousElement(
|
||||
reportAndCreateErroneousElement(
|
||||
node.selector, name.text, MessageKind.ASSIGNING_METHOD, const {});
|
||||
registry.registerFeature(Feature.THROW_NO_SUCH_METHOD);
|
||||
if (node.isComplex) {
|
||||
|
@ -2860,7 +2860,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
registry.registerStaticUse(new StaticUse.staticGet(member));
|
||||
}
|
||||
if (member.isFinal || member.isConst) {
|
||||
ErroneousElement error = reportAndCreateErroneousElement(
|
||||
reportAndCreateErroneousElement(
|
||||
node.selector,
|
||||
name.text,
|
||||
MessageKind.UNDEFINED_STATIC_SETTER_BUT_GETTER,
|
||||
|
@ -3613,7 +3613,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
ResolutionResult visitYield(Yield node) {
|
||||
if (!resolution.target.supportsAsyncAwait) {
|
||||
reporter.reportErrorMessage(
|
||||
node.yieldToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
reporter.spanFromToken(node.yieldToken),
|
||||
MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
} else {
|
||||
if (!currentAsyncMarker.isYielding) {
|
||||
reporter.reportErrorMessage(node, MessageKind.INVALID_YIELD);
|
||||
|
@ -3754,7 +3755,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
ResolutionResult visitAwait(Await node) {
|
||||
if (!resolution.target.supportsAsyncAwait) {
|
||||
reporter.reportErrorMessage(
|
||||
node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
reporter.spanFromToken(node.awaitToken),
|
||||
MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
} else {
|
||||
if (!currentAsyncMarker.isAsync) {
|
||||
reporter.reportErrorMessage(node, MessageKind.INVALID_AWAIT);
|
||||
|
@ -4017,7 +4019,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
if (resolution.commonElements.isSymbolConstructor(constructor) &&
|
||||
!resolution.mirrorUsageAnalyzerTask
|
||||
.hasMirrorUsage(enclosingElement)) {
|
||||
reporter.reportHintMessage(node.newToken, MessageKind.NON_CONST_BLOAT,
|
||||
reporter.reportHintMessage(reporter.spanFromToken(node.newToken),
|
||||
MessageKind.NON_CONST_BLOAT,
|
||||
{'name': commonElements.symbolClass.name});
|
||||
}
|
||||
registry.registerNewStructure(
|
||||
|
@ -4289,11 +4292,13 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
ResolutionResult visitAsyncForIn(AsyncForIn node) {
|
||||
if (!resolution.target.supportsAsyncAwait) {
|
||||
reporter.reportErrorMessage(
|
||||
node.awaitToken, MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
reporter.spanFromToken(node.awaitToken),
|
||||
MessageKind.ASYNC_AWAIT_NOT_SUPPORTED);
|
||||
} else {
|
||||
if (!currentAsyncMarker.isAsync) {
|
||||
reporter.reportErrorMessage(
|
||||
node.awaitToken, MessageKind.INVALID_AWAIT_FOR_IN);
|
||||
reporter.spanFromToken(node.awaitToken),
|
||||
MessageKind.INVALID_AWAIT_FOR_IN);
|
||||
}
|
||||
registry.registerFeature(Feature.ASYNC_FOR_IN);
|
||||
registry.registerDynamicUse(new DynamicUse(Selectors.current, null));
|
||||
|
@ -4693,7 +4698,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|||
visit(node.tryBlock);
|
||||
if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
|
||||
reporter.reportErrorMessage(
|
||||
node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
|
||||
reporter.spanFromToken(node.getEndToken().next),
|
||||
MessageKind.NO_CATCH_NOR_FINALLY);
|
||||
}
|
||||
visit(node.catchBlocks);
|
||||
visit(node.finallyBlock);
|
||||
|
|
|
@ -37,7 +37,7 @@ import '../elements/modelx.dart'
|
|||
TypedefElementX;
|
||||
import '../enqueue.dart';
|
||||
import '../options.dart';
|
||||
import '../tokens/token.dart'
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show
|
||||
isBinaryOperator,
|
||||
isMinusOperator,
|
||||
|
@ -47,7 +47,7 @@ import '../tokens/token.dart'
|
|||
import '../tree/tree.dart';
|
||||
import '../universe/call_structure.dart' show CallStructure;
|
||||
import '../universe/feature.dart' show Feature;
|
||||
import '../universe/use.dart' show StaticUse, TypeUse;
|
||||
import '../universe/use.dart' show StaticUse;
|
||||
import '../universe/world_impact.dart' show WorldImpact;
|
||||
import '../util/util.dart' show Link, Setlet;
|
||||
import '../world.dart';
|
||||
|
@ -518,7 +518,6 @@ class ResolverTask extends CompilerTask {
|
|||
ResolvedAst resolvedAst = factory.resolvedAst;
|
||||
assert(invariant(node, resolvedAst != null,
|
||||
message: 'No ResolvedAst for $factory.'));
|
||||
FunctionExpression functionNode = resolvedAst.node;
|
||||
RedirectingFactoryBody redirectionNode = resolvedAst.body;
|
||||
ResolutionDartType factoryType =
|
||||
resolvedAst.elements.getType(redirectionNode);
|
||||
|
|
|
@ -18,7 +18,6 @@ import '../elements/modelx.dart'
|
|||
LocalParameterElementX,
|
||||
TypeVariableElementX;
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/use.dart' show TypeUse;
|
||||
import '../util/util.dart' show Link, LinkBuilder;
|
||||
import 'members.dart' show ResolverVisitor;
|
||||
import 'registry.dart' show ResolutionRegistry;
|
||||
|
|
|
@ -8,7 +8,6 @@ import '../common.dart';
|
|||
import '../common/resolution.dart';
|
||||
import '../elements/modelx.dart' show LocalVariableElementX, VariableList;
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/use.dart' show TypeUse;
|
||||
import '../universe/feature.dart';
|
||||
import '../util/util.dart' show Link;
|
||||
import 'members.dart' show ResolverVisitor;
|
||||
|
|
|
@ -9,11 +9,12 @@ import '../diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
|
|||
import '../elements/elements.dart' show CompilationUnitElement, LibraryElement;
|
||||
import '../parser/diet_parser_task.dart' show DietParserTask;
|
||||
import '../script.dart' show Script;
|
||||
import '../tokens/token.dart' show Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show COMMENT_TOKEN, EOF_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner.dart'
|
||||
show Scanner, StringScanner, Token, Utf8BytesScanner;
|
||||
import 'package:front_end/src/fasta/scanner/token_constants.dart' as Tokens
|
||||
show COMMENT_TOKEN, EOF_TOKEN;
|
||||
import '../tokens/token_map.dart' show TokenMap;
|
||||
import 'scanner.dart' show Scanner;
|
||||
import 'string_scanner.dart' show StringScanner;
|
||||
import '../io/source_file.dart';
|
||||
|
||||
class ScannerTask extends CompilerTask {
|
||||
final DietParserTask _dietParser;
|
||||
|
@ -52,10 +53,17 @@ class ScannerTask extends CompilerTask {
|
|||
});
|
||||
}
|
||||
|
||||
Token scanFile(SourceFile file, {bool includeComments: false}) {
|
||||
Scanner scanner = file is Utf8BytesSourceFile
|
||||
? new Utf8BytesScanner(file.slowUtf8ZeroTerminatedBytes(),
|
||||
includeComments: includeComments)
|
||||
: new StringScanner(file.slowText(), includeComments: includeComments);
|
||||
return measure(scanner.tokenize);
|
||||
}
|
||||
|
||||
void scanElements(CompilationUnitElement compilationUnit) {
|
||||
Script script = compilationUnit.script;
|
||||
Token tokens =
|
||||
new Scanner(script.file, includeComments: _preserveComments).tokenize();
|
||||
Token tokens = scanFile(script.file, includeComments: _preserveComments);
|
||||
if (_preserveComments) {
|
||||
tokens = processAndStripComments(tokens);
|
||||
}
|
||||
|
@ -71,8 +79,7 @@ class ScannerTask extends CompilerTask {
|
|||
*/
|
||||
Token tokenize(String source) {
|
||||
return measure(() {
|
||||
return new StringScanner.fromString(source, includeComments: false)
|
||||
.tokenize();
|
||||
return new StringScanner(source, includeComments: false).tokenize();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import '../native/native.dart' show NativeBehavior;
|
|||
import '../resolution/access_semantics.dart';
|
||||
import '../resolution/send_structure.dart';
|
||||
import '../resolution/tree_elements.dart';
|
||||
import '../tokens/token.dart';
|
||||
import 'package:front_end/src/fasta/scanner.dart';
|
||||
import '../tree/nodes.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../universe/feature.dart';
|
||||
|
@ -1437,7 +1437,10 @@ class NodeEquivalenceVisitor implements Visitor1<bool, Node> {
|
|||
(Token t1, Token t2) {
|
||||
if (t1 == t2) return true;
|
||||
if (t1 == null || t2 == null) return false;
|
||||
return strategy.test(t1, t2, 'hashCode', t1.hashCode, t2.hashCode);
|
||||
return
|
||||
strategy.test(t1, t2, 'charOffset', t1.charOffset, t2.charOffset) &&
|
||||
strategy.test(t1, t2, 'info', t1.info, t2.info) &&
|
||||
strategy.test(t1, t2, 'value', t1.value, t2.value);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ import '../resolution/scope.dart' show Scope;
|
|||
import '../resolution/tree_elements.dart' show TreeElements;
|
||||
import '../script.dart';
|
||||
import '../serialization/constant_serialization.dart';
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../tree/tree.dart';
|
||||
import '../util/util.dart' show Link, LinkBuilder;
|
||||
import 'keys.dart';
|
||||
|
@ -1572,7 +1572,6 @@ abstract class MemberElementMixin
|
|||
@override
|
||||
bool get isInjected => _decoder.getBool(Key.IS_INJECTED);
|
||||
|
||||
@override
|
||||
void forgetElement() {
|
||||
nestedClosures.clear();
|
||||
}
|
||||
|
|
|
@ -11,16 +11,14 @@ import '../elements/resolution_types.dart';
|
|||
import '../diagnostics/diagnostic_listener.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../elements/modelx.dart';
|
||||
import '../parser/listener.dart' show ParserError;
|
||||
import 'package:front_end/src/fasta/parser.dart' show Parser, ParserError;
|
||||
import '../parser/node_listener.dart' show NodeListener;
|
||||
import '../parser/parser.dart' show Parser;
|
||||
import '../resolution/enum_creator.dart';
|
||||
import '../resolution/send_structure.dart';
|
||||
import '../resolution/tree_elements.dart';
|
||||
import '../tokens/token.dart';
|
||||
import 'package:front_end/src/fasta/scanner.dart';
|
||||
import '../tree/tree.dart';
|
||||
import '../universe/selector.dart';
|
||||
import '../util/util.dart';
|
||||
import 'keys.dart';
|
||||
import 'modelz.dart';
|
||||
import 'serialization.dart';
|
||||
|
@ -374,7 +372,6 @@ class ResolvedAstDeserializer {
|
|||
ParsingContext parsing,
|
||||
Token getBeginToken(Uri uri, int charOffset),
|
||||
DeserializerPlugin nativeDataDeserializer) {
|
||||
CompilationUnitElement compilationUnit = element.compilationUnit;
|
||||
DiagnosticReporter reporter = parsing.reporter;
|
||||
Uri uri = objectDecoder.getUri(Key.URI);
|
||||
|
||||
|
@ -395,7 +392,6 @@ class ResolvedAstDeserializer {
|
|||
Node doParse(parse(Parser parser)) {
|
||||
return parsing.measure(() {
|
||||
return reporter.withCurrentElement(element, () {
|
||||
CompilationUnitElement unit = element.compilationUnit;
|
||||
NodeListener listener = new NodeListener(
|
||||
parsing.getScannerOptionsFor(element), reporter, null);
|
||||
listener.memberErrors = listener.memberErrors.prepend(false);
|
||||
|
@ -424,7 +420,6 @@ class ResolvedAstDeserializer {
|
|||
case AstKind.ENUM_VALUES_FIELD:
|
||||
EnumClassElement enumClass = element.enclosingClass;
|
||||
AstBuilder builder = new AstBuilder(element.sourcePosition.begin);
|
||||
List<FieldElement> enumValues = <FieldElement>[];
|
||||
List<Node> valueReferences = <Node>[];
|
||||
for (EnumConstantElement enumConstant in enumClass.enumValues) {
|
||||
AstBuilder valueBuilder =
|
||||
|
@ -532,7 +527,6 @@ class ResolvedAstDeserializer {
|
|||
Node root = computeNode(kind);
|
||||
TreeElementMapping elements = new TreeElementMapping(element);
|
||||
AstIndexComputer indexComputer = new AstIndexComputer();
|
||||
Map<Node, int> nodeIndices = indexComputer.nodeIndices;
|
||||
List<Node> nodeList = indexComputer.nodeList;
|
||||
root.accept(indexComputer);
|
||||
elements.containsTryStatement = objectDecoder.getBool(Key.CONTAINS_TRY);
|
||||
|
|
|
@ -659,7 +659,6 @@ bool includeAllElements(Element element) => true;
|
|||
class Serializer {
|
||||
List<SerializerPlugin> plugins = <SerializerPlugin>[];
|
||||
|
||||
Map<Uri, dynamic> _dependencyMap = <Uri, dynamic>{};
|
||||
Map<Element, DataObject> _elementMap = <Element, DataObject>{};
|
||||
Map<ConstantExpression, DataObject> _constantMap =
|
||||
<ConstantExpression, DataObject>{};
|
||||
|
|
|
@ -52,9 +52,6 @@ Selector deserializeSelector(ObjectDecoder decoder) {
|
|||
int argumentCount = decoder.getInt(Key.ARGUMENTS);
|
||||
List<String> namedArguments =
|
||||
decoder.getStrings(Key.NAMED_ARGUMENTS, isOptional: true);
|
||||
String name = decoder.getString(Key.NAME);
|
||||
bool isSetter = decoder.getBool(Key.IS_SETTER);
|
||||
LibraryElement library = decoder.getElement(Key.LIBRARY, isOptional: true);
|
||||
return new Selector(kind, deserializeName(decoder),
|
||||
new CallStructure(argumentCount, namedArguments));
|
||||
}
|
||||
|
|
|
@ -11,10 +11,9 @@ import '../common/resolution.dart';
|
|||
import '../compiler.dart';
|
||||
import '../elements/resolution_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../scanner/scanner.dart';
|
||||
import '../script.dart';
|
||||
import '../serialization/impact_serialization.dart';
|
||||
import '../tokens/token.dart';
|
||||
import 'package:front_end/src/fasta/scanner.dart';
|
||||
import '../universe/call_structure.dart';
|
||||
import '../universe/use.dart';
|
||||
import '../universe/world_impact.dart';
|
||||
|
@ -315,7 +314,7 @@ class ResolvedAstDeserializerPlugin extends DeserializerPlugin {
|
|||
'No source file found for $uri in:\n ${scripts.keys.join('\n ')}');
|
||||
}
|
||||
if (script.isSynthesized) return null;
|
||||
return new Scanner(script.file).tokenize();
|
||||
return parsingContext.scanner.scanFile(script.file);
|
||||
});
|
||||
if (beginToken == null) return null;
|
||||
return ResolvedAstDeserializer.findTokenInStream(beginToken, offset);
|
||||
|
|
|
@ -10,7 +10,6 @@ import '../common/resolution.dart' show ResolutionImpact, ResolutionWorkItem;
|
|||
import '../common/tasks.dart' show CompilerTask;
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../elements/elements.dart';
|
||||
import '../enqueue.dart' show ResolutionEnqueuer;
|
||||
import '../universe/world_impact.dart' show WorldImpact;
|
||||
import 'json_serializer.dart';
|
||||
import 'serialization.dart';
|
||||
|
|
|
@ -1140,7 +1140,6 @@ class SsaBuilder extends ast.Visitor
|
|||
if (compiler.elementHasCompileTimeError(member)) return;
|
||||
reporter.withCurrentElement(member, () {
|
||||
ResolvedAst fieldResolvedAst = member.resolvedAst;
|
||||
ast.Node node = fieldResolvedAst.node;
|
||||
ast.Expression initializer = fieldResolvedAst.body;
|
||||
if (initializer == null) {
|
||||
// Unassigned fields of native classes are not initialized to
|
||||
|
|
|
@ -26,7 +26,7 @@ import '../kernel/kernel.dart';
|
|||
import '../native/native.dart' as native;
|
||||
import '../resolution/tree_elements.dart';
|
||||
import '../tree/dartstring.dart';
|
||||
import '../tree/nodes.dart' show Node, BreakStatement;
|
||||
import '../tree/nodes.dart' show Node;
|
||||
import '../types/masks.dart';
|
||||
import '../universe/call_structure.dart' show CallStructure;
|
||||
import '../universe/selector.dart';
|
||||
|
@ -663,7 +663,6 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
|||
returnStatement.expression.accept(this);
|
||||
value = pop();
|
||||
if (_targetFunction.asyncMarker == ir.AsyncMarker.Async) {
|
||||
var returnType = astAdapter.getDartType(_targetFunction.returnType);
|
||||
if (compiler.options.enableTypeAssertions &&
|
||||
!isValidAsyncReturnType(_targetFunction.returnType)) {
|
||||
generateTypeError(
|
||||
|
@ -1309,12 +1308,12 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
|||
int switchIndex = 1;
|
||||
bool hasDefault = false;
|
||||
for (ir.SwitchCase switchCase in switchStatement.cases) {
|
||||
if (_isDefaultCase(switchCase)) {
|
||||
hasDefault = true;
|
||||
}
|
||||
if (SwitchContinueAnalysis.containsContinue(switchCase.body)) {
|
||||
hasContinue = true;
|
||||
}
|
||||
if (switchCase.isDefault) {
|
||||
hasDefault = true;
|
||||
}
|
||||
caseIndex[switchCase] = switchIndex;
|
||||
switchIndex++;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
// 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.
|
||||
|
||||
import '../common.dart';
|
||||
import '../common/codegen.dart' show CodegenRegistry;
|
||||
import '../compiler.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../elements/entities.dart';
|
||||
import '../elements/entities.dart' show Entity, Local;
|
||||
import '../elements/resolution_types.dart';
|
||||
import '../js_backend/js_backend.dart';
|
||||
import '../resolution/tree_elements.dart';
|
||||
|
|
|
@ -6,7 +6,6 @@ import '../common.dart';
|
|||
import '../elements/elements.dart';
|
||||
import '../tree/tree.dart' as ast;
|
||||
|
||||
import 'builder.dart';
|
||||
import 'graph_builder.dart';
|
||||
import 'locals_handler.dart';
|
||||
import 'nodes.dart';
|
||||
|
|
|
@ -6,7 +6,6 @@ import 'package:js_runtime/shared/embedded_names.dart';
|
|||
import 'package:kernel/ast.dart' as ir;
|
||||
|
||||
import '../common.dart';
|
||||
import '../common/names.dart';
|
||||
import '../compiler.dart';
|
||||
import '../constants/expressions.dart';
|
||||
import '../constants/values.dart';
|
||||
|
@ -17,7 +16,6 @@ import '../elements/entities.dart';
|
|||
import '../elements/modelx.dart';
|
||||
import '../elements/types.dart';
|
||||
import '../js/js.dart' as js;
|
||||
import '../js_backend/backend_helpers.dart';
|
||||
import '../js_backend/js_backend.dart';
|
||||
import '../kernel/element_adapter.dart';
|
||||
import '../kernel/kernel.dart';
|
||||
|
@ -766,7 +764,7 @@ class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
|
|||
ConstantExpression visitStaticGet(ir.StaticGet node) {
|
||||
Element element = astAdapter.getMember(node.target);
|
||||
if (element.isField) {
|
||||
return new VariableConstantExpression(element);
|
||||
return new VariableConstantExpression(element as VariableElement);
|
||||
}
|
||||
astAdapter.reporter.internalError(
|
||||
CURRENT_ELEMENT_SPANNABLE, "Unexpected constant target: $element.");
|
||||
|
|
|
@ -487,7 +487,6 @@ class LocalsHandler {
|
|||
Map<Local, HInstruction> savedDirectLocals =
|
||||
new Map<Local, HInstruction>.from(directLocals);
|
||||
|
||||
JavaScriptBackend backend = _compiler.backend;
|
||||
// Create phis for all elements in the definitions environment.
|
||||
savedDirectLocals.forEach((Local local, HInstruction instruction) {
|
||||
if (isAccessedDirectly(local)) {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import '../compiler.dart';
|
||||
import '../io/source_information.dart';
|
||||
import '../js_backend/js_backend.dart';
|
||||
import '../tree/tree.dart' as ast;
|
||||
|
||||
import 'graph_builder.dart';
|
||||
|
|
|
@ -9,10 +9,10 @@ library stringvalidator;
|
|||
import 'dart:collection';
|
||||
|
||||
import 'common.dart';
|
||||
import 'tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import 'tree/dartstring.dart' show DartString;
|
||||
import 'tree/nodes.dart' show StringQuoting;
|
||||
import 'util/characters.dart';
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart';
|
||||
|
||||
class StringValidator {
|
||||
final DiagnosticReporter reporter;
|
||||
|
@ -100,7 +100,8 @@ class StringValidator {
|
|||
|
||||
void stringParseError(String message, Token token, int offset) {
|
||||
reporter.reportErrorMessage(
|
||||
token, MessageKind.GENERIC, {'text': "$message @ $offset"});
|
||||
reporter.spanFromToken(token), MessageKind.GENERIC,
|
||||
{'text': "$message @ $offset"});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) 2015, 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 dart2js.tokens.precedence;
|
||||
|
||||
import '../util/util.dart' show computeHashCode;
|
||||
|
||||
class PrecedenceInfo {
|
||||
final String value;
|
||||
final int precedence;
|
||||
final int kind;
|
||||
|
||||
const PrecedenceInfo(this.value, this.precedence, this.kind);
|
||||
|
||||
toString() => 'PrecedenceInfo($value, $precedence, $kind)';
|
||||
|
||||
int get hashCode => computeHashCode(value, precedence, kind);
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
library dart2js.tokens.token_map;
|
||||
|
||||
import 'token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
|
||||
/**
|
||||
* Key class used in [TokenMap] in which the hash code for a token is based
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
import 'dart:collection';
|
||||
|
||||
import '../util/characters.dart';
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart';
|
||||
|
||||
/**
|
||||
* The [DartString] type represents a Dart string value as a sequence of Unicode
|
||||
|
|
|
@ -8,14 +8,17 @@ import '../common.dart';
|
|||
import '../elements/elements.dart' show MetadataAnnotation;
|
||||
import '../resolution/secret_tree_element.dart'
|
||||
show NullTreeElementMixin, StoredTreeElementMixin;
|
||||
import '../tokens/precedence_constants.dart' as Precedence show FUNCTION_INFO;
|
||||
import '../tokens/token.dart' show BeginGroupToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show PLUS_TOKEN;
|
||||
import '../util/characters.dart';
|
||||
import 'package:front_end/src/fasta/scanner/precedence.dart' as Precedence
|
||||
show FUNCTION_INFO;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show BeginGroupToken, Token;
|
||||
import 'package:front_end/src/fasta/scanner/token_constants.dart' as Tokens
|
||||
show PLUS_TOKEN;
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart';
|
||||
import '../util/util.dart';
|
||||
import 'dartstring.dart';
|
||||
import 'prettyprint.dart';
|
||||
import 'unparser.dart';
|
||||
import 'package:front_end/src/fasta/parser.dart' show ErrorKind;
|
||||
|
||||
abstract class Visitor<R> {
|
||||
const Visitor();
|
||||
|
@ -478,7 +481,7 @@ class ClassNode extends Node {
|
|||
if (token == null) {
|
||||
token = name.getEndToken();
|
||||
}
|
||||
assert(invariant(beginToken, token != null));
|
||||
assert(token != null);
|
||||
return token;
|
||||
}
|
||||
|
||||
|
@ -3086,17 +3089,19 @@ class IsInterpolationVisitor extends Visitor<bool> {
|
|||
class ErrorNode extends Node
|
||||
implements FunctionExpression, VariableDefinitions, Typedef {
|
||||
final Token token;
|
||||
final String reason;
|
||||
final ErrorKind kind;
|
||||
final Map arguments;
|
||||
final Identifier name;
|
||||
final NodeList definitions;
|
||||
|
||||
ErrorNode.internal(this.token, this.reason, this.name, this.definitions);
|
||||
ErrorNode.internal(
|
||||
this.token, this.kind, this.arguments, this.name, this.definitions);
|
||||
|
||||
factory ErrorNode(Token token, String reason) {
|
||||
factory ErrorNode(Token token, ErrorKind kind, Map arguments) {
|
||||
Identifier name = new Identifier(token);
|
||||
NodeList definitions =
|
||||
new NodeList(null, const Link<Node>().prepend(name), null, null);
|
||||
return new ErrorNode.internal(token, reason, name, definitions);
|
||||
return new ErrorNode.internal(token, kind, arguments, name, definitions);
|
||||
}
|
||||
|
||||
Token get beginToken => token;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// 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.
|
||||
|
||||
import '../tokens/token.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import '../util/util.dart';
|
||||
import 'nodes.dart';
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
// 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.
|
||||
|
||||
import '../tokens/token.dart' show Token;
|
||||
import '../tokens/token_constants.dart' as Tokens
|
||||
import 'package:front_end/src/fasta/scanner.dart' show Token;
|
||||
import 'package:front_end/src/fasta/scanner/token_constants.dart' as Tokens
|
||||
show IDENTIFIER_TOKEN, KEYWORD_TOKEN, PLUS_TOKEN;
|
||||
import '../util/util.dart';
|
||||
import 'nodes.dart';
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
library types.constants;
|
||||
|
||||
import '../common.dart';
|
||||
import '../constants/constant_system.dart' show ConstantSystem;
|
||||
import '../compiler.dart' show Compiler;
|
||||
import '../constants/values.dart';
|
||||
import '../js_backend/js_backend.dart'
|
||||
show JavaScriptBackend, SyntheticConstantKind;
|
||||
import '../js_backend/js_backend.dart' show SyntheticConstantKind;
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'masks.dart';
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
library dart2js.call_structure;
|
||||
|
||||
import '../common.dart';
|
||||
import '../common/names.dart' show Names;
|
||||
import '../elements/types.dart' show FunctionType;
|
||||
import '../util/util.dart';
|
||||
|
|
|
@ -6,7 +6,6 @@ library dart2js.world.class_set;
|
|||
|
||||
import 'dart:collection' show IterableBase;
|
||||
|
||||
import '../common.dart';
|
||||
import '../elements/elements.dart' show ClassElement;
|
||||
import '../util/enumset.dart' show EnumSet;
|
||||
import '../util/util.dart' show Link;
|
||||
|
|
|
@ -22,7 +22,6 @@ import '../universe/function_set.dart' show FunctionSetBuilder;
|
|||
import '../util/enumset.dart';
|
||||
import '../util/util.dart';
|
||||
import '../world.dart' show World, ClosedWorld, ClosedWorldImpl, OpenWorld;
|
||||
import 'call_structure.dart' show CallStructure;
|
||||
import 'selector.dart' show Selector;
|
||||
import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
library dart2js.universe.world_impact;
|
||||
|
||||
import '../elements/elements.dart' show Element;
|
||||
import '../util/util.dart' show Setlet;
|
||||
import 'use.dart' show DynamicUse, StaticUse, TypeUse;
|
||||
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
library dart2js.util;
|
||||
|
||||
import 'characters.dart';
|
||||
import 'util_implementation.dart';
|
||||
import 'package:front_end/src/fasta/scanner/characters.dart';
|
||||
import 'package:front_end/src/fasta/util/link.dart';
|
||||
|
||||
export 'emptyset.dart';
|
||||
export 'maplet.dart';
|
||||
export 'setlet.dart';
|
||||
export 'package:front_end/src/fasta/util/link.dart';
|
||||
|
||||
part 'indentation.dart';
|
||||
part 'link.dart';
|
||||
|
||||
/// Helper functions for creating hash codes.
|
||||
class Hashing {
|
||||
|
|
42
pkg/front_end/lib/src/fasta/parser.dart
Normal file
42
pkg/front_end/lib/src/fasta/parser.dart
Normal file
|
@ -0,0 +1,42 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.parser;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner/token.dart' show
|
||||
Token;
|
||||
|
||||
import 'parser/listener.dart' show
|
||||
Listener;
|
||||
|
||||
import 'parser/parser.dart' show
|
||||
Parser;
|
||||
|
||||
import 'parser/listener.dart' show
|
||||
ParserError;
|
||||
|
||||
export 'parser/parser.dart' show
|
||||
Parser,
|
||||
closeBraceFor,
|
||||
optional;
|
||||
|
||||
export 'parser/listener.dart' show
|
||||
Listener,
|
||||
ParserError;
|
||||
|
||||
export 'parser/error_kind.dart' show
|
||||
ErrorKind;
|
||||
|
||||
export 'parser/top_level_parser.dart' show
|
||||
TopLevelParser;
|
||||
|
||||
export 'parser/class_member_parser.dart' show
|
||||
ClassMemberParser;
|
||||
|
||||
List<ParserError> parse(Token tokens) {
|
||||
Listener listener = new Listener();
|
||||
Parser parser = new Parser(listener);
|
||||
parser.parseUnit(tokens);
|
||||
return listener.recoverableErrors;
|
||||
}
|
7
pkg/front_end/lib/src/fasta/parser/bin/parser.dart
Normal file
7
pkg/front_end/lib/src/fasta/parser/bin/parser.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
// 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.
|
||||
|
||||
import 'package:front_end/src/fasta/parser/main.dart' as dart_parser;
|
||||
|
||||
main(List<String> arguments) => dart_parser.main(arguments);
|
|
@ -2,174 +2,32 @@
|
|||
// 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 dart2js.parser.partial;
|
||||
library fasta.parser.class_member_parser;
|
||||
|
||||
import '../common.dart';
|
||||
import '../tokens/token.dart' show BeginGroupToken, ErrorToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
|
||||
import 'listener.dart' show Listener;
|
||||
import 'parser.dart' show Parser;
|
||||
import 'package:front_end/src/fasta/scanner/token.dart' show
|
||||
Token;
|
||||
|
||||
class PartialParser extends Parser {
|
||||
PartialParser(Listener listener) : super(listener);
|
||||
import 'listener.dart' show
|
||||
Listener;
|
||||
|
||||
Token parseClassBody(Token token) => skipClassBody(token);
|
||||
import 'parser.dart' show
|
||||
Parser;
|
||||
|
||||
Token fullParseClassBody(Token token) => super.parseClassBody(token);
|
||||
/// Parser similar to [TopLevelParser] but also parses class members (excluding
|
||||
/// their bodies).
|
||||
class ClassMemberParser extends Parser {
|
||||
ClassMemberParser(Listener listener,
|
||||
{bool asyncAwaitKeywordsEnabled: false})
|
||||
: super(listener, asyncAwaitKeywordsEnabled: asyncAwaitKeywordsEnabled);
|
||||
|
||||
Token parseExpression(Token token) => skipExpression(token);
|
||||
|
||||
Token parseArgumentsOpt(Token token) {
|
||||
// This method is overridden for two reasons:
|
||||
// 1. Avoid generating events for arguments.
|
||||
// 2. Avoid calling skip expression for each argument (which doesn't work).
|
||||
listener.handleNoArguments(token);
|
||||
if (optional('(', token)) {
|
||||
BeginGroupToken begin = token;
|
||||
return begin.endGroup.next;
|
||||
} else {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
Token skipExpression(Token token) {
|
||||
while (true) {
|
||||
final kind = token.kind;
|
||||
final value = token.stringValue;
|
||||
if ((identical(kind, Tokens.EOF_TOKEN)) ||
|
||||
(identical(value, ';')) ||
|
||||
(identical(value, ',')) ||
|
||||
(identical(value, '}')) ||
|
||||
(identical(value, ')')) ||
|
||||
(identical(value, ']'))) {
|
||||
break;
|
||||
}
|
||||
if (identical(value, '=') ||
|
||||
identical(value, '?') ||
|
||||
identical(value, ':') ||
|
||||
identical(value, '??')) {
|
||||
var nextValue = token.next.stringValue;
|
||||
if (identical(nextValue, 'const')) {
|
||||
token = token.next;
|
||||
nextValue = token.next.stringValue;
|
||||
}
|
||||
if (identical(nextValue, '{')) {
|
||||
// Handle cases like this:
|
||||
// class Foo {
|
||||
// var map;
|
||||
// Foo() : map = {};
|
||||
// Foo.x() : map = true ? {} : {};
|
||||
// }
|
||||
BeginGroupToken begin = token.next;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
continue;
|
||||
}
|
||||
if (identical(nextValue, '<')) {
|
||||
// Handle cases like this:
|
||||
// class Foo {
|
||||
// var map;
|
||||
// Foo() : map = <String, Foo>{};
|
||||
// Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{};
|
||||
// }
|
||||
BeginGroupToken begin = token.next;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
if (identical(token.stringValue, '{')) {
|
||||
begin = token;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!mayParseFunctionExpressions && identical(value, '{')) {
|
||||
break;
|
||||
}
|
||||
if (token is BeginGroupToken) {
|
||||
BeginGroupToken begin = token;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
} else if (token is ErrorToken) {
|
||||
listener.reportErrorToken(token);
|
||||
}
|
||||
token = token.next;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token skipClassBody(Token token) {
|
||||
if (!optional('{', token)) {
|
||||
return listener.expectedClassBodyToSkip(token);
|
||||
}
|
||||
BeginGroupToken beginGroupToken = token;
|
||||
Token endGroup = beginGroupToken.endGroup;
|
||||
if (endGroup == null) {
|
||||
return listener.unmatched(beginGroupToken);
|
||||
} else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) {
|
||||
return listener.unmatched(beginGroupToken);
|
||||
}
|
||||
return endGroup;
|
||||
}
|
||||
|
||||
Token skipAsyncModifier(Token token) {
|
||||
String value = token.stringValue;
|
||||
if (identical(value, 'async')) {
|
||||
token = token.next;
|
||||
value = token.stringValue;
|
||||
|
||||
if (identical(value, '*')) {
|
||||
token = token.next;
|
||||
}
|
||||
} else if (identical(value, 'sync')) {
|
||||
token = token.next;
|
||||
value = token.stringValue;
|
||||
|
||||
if (identical(value, '*')) {
|
||||
token = token.next;
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
// This method is overridden for two reasons:
|
||||
// 1. Avoid generating events for arguments.
|
||||
// 2. Avoid calling skip expression for each argument (which doesn't work).
|
||||
Token parseArgumentsOpt(Token token) => skipArgumentsOpt(token);
|
||||
|
||||
Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
|
||||
assert(!isExpression);
|
||||
token = skipAsyncModifier(token);
|
||||
String value = token.stringValue;
|
||||
if (identical(value, ';')) {
|
||||
if (!allowAbstract) {
|
||||
listener.reportError(token, MessageKind.BODY_EXPECTED);
|
||||
}
|
||||
listener.handleNoFunctionBody(token);
|
||||
} else {
|
||||
if (identical(value, '=>')) {
|
||||
token = parseExpression(token.next);
|
||||
expectSemicolon(token);
|
||||
} else if (value == '=') {
|
||||
token = parseRedirectingFactoryBody(token);
|
||||
expectSemicolon(token);
|
||||
} else {
|
||||
token = skipBlock(token);
|
||||
}
|
||||
listener.skippedFunctionBody(token);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token parseFormalParameters(Token token) => skipFormals(token);
|
||||
|
||||
Token skipFormals(Token token) {
|
||||
listener.beginOptionalFormalParameters(token);
|
||||
if (!optional('(', token)) {
|
||||
if (optional(';', token)) {
|
||||
listener.recoverableError(token, "expected '('");
|
||||
return token;
|
||||
}
|
||||
return listener.unexpected(token);
|
||||
}
|
||||
BeginGroupToken beginGroupToken = token;
|
||||
Token endToken = beginGroupToken.endGroup;
|
||||
listener.endFormalParameters(0, token, endToken);
|
||||
return endToken.next;
|
||||
return skipFunctionBody(token, isExpression, allowAbstract);
|
||||
}
|
||||
}
|
||||
|
|
41
pkg/front_end/lib/src/fasta/parser/error_kind.dart
Normal file
41
pkg/front_end/lib/src/fasta/parser/error_kind.dart
Normal file
|
@ -0,0 +1,41 @@
|
|||
// 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 fasta.parser.error_kind;
|
||||
|
||||
enum ErrorKind {
|
||||
EmptyNamedParameterList,
|
||||
EmptyOptionalParameterList,
|
||||
ExpectedBlockToSkip,
|
||||
ExpectedBody,
|
||||
ExpectedButGot,
|
||||
ExpectedClassBody,
|
||||
ExpectedClassBodyToSkip,
|
||||
ExpectedDeclaration,
|
||||
ExpectedExpression,
|
||||
ExpectedFunctionBody,
|
||||
ExpectedHexDigit,
|
||||
ExpectedIdentifier,
|
||||
ExpectedOpenParens,
|
||||
ExpectedString,
|
||||
ExpectedType,
|
||||
ExtraneousModifier,
|
||||
ExtraneousModifierReplace,
|
||||
InvalidAwaitFor,
|
||||
InvalidInputCharacter,
|
||||
InvalidSyncModifier,
|
||||
InvalidVoid,
|
||||
MalformedStringLiteral,
|
||||
MissingExponent,
|
||||
PositionalParameterWithEquals,
|
||||
RequiredParameterWithDefault,
|
||||
UnexpectedToken,
|
||||
UnmatchedToken,
|
||||
UnsupportedPrefixPlus,
|
||||
UnterminatedComment,
|
||||
UnterminatedString,
|
||||
UnterminatedToken,
|
||||
|
||||
Unspecified,
|
||||
}
|
File diff suppressed because it is too large
Load diff
57
pkg/front_end/lib/src/fasta/parser/main.dart
Normal file
57
pkg/front_end/lib/src/fasta/parser/main.dart
Normal file
|
@ -0,0 +1,57 @@
|
|||
// 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 fasta.parser.main;
|
||||
|
||||
import 'dart:convert' show
|
||||
LineSplitter,
|
||||
UTF8;
|
||||
|
||||
import 'dart:io' show
|
||||
File;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner/token.dart' show
|
||||
Token;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner/io.dart' show
|
||||
readBytesFromFileSync;
|
||||
|
||||
import 'package:front_end/src/fasta/scanner.dart' show
|
||||
scan;
|
||||
|
||||
import 'listener.dart' show
|
||||
Listener;
|
||||
|
||||
import 'top_level_parser.dart' show
|
||||
TopLevelParser;
|
||||
|
||||
class DebugListener extends Listener {
|
||||
void handleIdentifier(Token token) {
|
||||
logEvent("Identifier: ${token.value}");
|
||||
}
|
||||
|
||||
void logEvent(String name) {
|
||||
print(name);
|
||||
}
|
||||
}
|
||||
|
||||
main(List<String> arguments) async {
|
||||
for (String argument in arguments) {
|
||||
if (argument.startsWith("@")) {
|
||||
Uri uri = Uri.base.resolve(argument.substring(1));
|
||||
await for (String file in new File.fromUri(uri).openRead()
|
||||
.transform(UTF8.decoder)
|
||||
.transform(const LineSplitter())) {
|
||||
outLine(uri.resolve(file));
|
||||
}
|
||||
} else {
|
||||
outLine(Uri.base.resolve(argument));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void outLine(Uri uri) {
|
||||
new TopLevelParser(new DebugListener()).parseUnit(
|
||||
scan(readBytesFromFileSync(uri)).tokens);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -2,174 +2,22 @@
|
|||
// 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 dart2js.parser.partial;
|
||||
library fasta.parser.top_level_parser;
|
||||
|
||||
import '../common.dart';
|
||||
import '../tokens/token.dart' show BeginGroupToken, ErrorToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
|
||||
import '../util/characters.dart' as Characters show $CLOSE_CURLY_BRACKET;
|
||||
import 'listener.dart' show Listener;
|
||||
import 'parser.dart' show Parser;
|
||||
import 'package:front_end/src/fasta/scanner/token.dart' show
|
||||
Token;
|
||||
|
||||
class PartialParser extends Parser {
|
||||
PartialParser(Listener listener) : super(listener);
|
||||
import 'listener.dart' show
|
||||
Listener;
|
||||
|
||||
import 'class_member_parser.dart' show
|
||||
ClassMemberParser;
|
||||
|
||||
/// Parser which only parses top-level elements, but ignores their bodies.
|
||||
/// Use [Parser] to parse everything.
|
||||
class TopLevelParser extends ClassMemberParser {
|
||||
TopLevelParser(Listener listener, {bool asyncAwaitKeywordsEnabled: false})
|
||||
: super(listener, asyncAwaitKeywordsEnabled: asyncAwaitKeywordsEnabled);
|
||||
|
||||
Token parseClassBody(Token token) => skipClassBody(token);
|
||||
|
||||
Token fullParseClassBody(Token token) => super.parseClassBody(token);
|
||||
|
||||
Token parseExpression(Token token) => skipExpression(token);
|
||||
|
||||
Token parseArgumentsOpt(Token token) {
|
||||
// This method is overridden for two reasons:
|
||||
// 1. Avoid generating events for arguments.
|
||||
// 2. Avoid calling skip expression for each argument (which doesn't work).
|
||||
listener.handleNoArguments(token);
|
||||
if (optional('(', token)) {
|
||||
BeginGroupToken begin = token;
|
||||
return begin.endGroup.next;
|
||||
} else {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
Token skipExpression(Token token) {
|
||||
while (true) {
|
||||
final kind = token.kind;
|
||||
final value = token.stringValue;
|
||||
if ((identical(kind, Tokens.EOF_TOKEN)) ||
|
||||
(identical(value, ';')) ||
|
||||
(identical(value, ',')) ||
|
||||
(identical(value, '}')) ||
|
||||
(identical(value, ')')) ||
|
||||
(identical(value, ']'))) {
|
||||
break;
|
||||
}
|
||||
if (identical(value, '=') ||
|
||||
identical(value, '?') ||
|
||||
identical(value, ':') ||
|
||||
identical(value, '??')) {
|
||||
var nextValue = token.next.stringValue;
|
||||
if (identical(nextValue, 'const')) {
|
||||
token = token.next;
|
||||
nextValue = token.next.stringValue;
|
||||
}
|
||||
if (identical(nextValue, '{')) {
|
||||
// Handle cases like this:
|
||||
// class Foo {
|
||||
// var map;
|
||||
// Foo() : map = {};
|
||||
// Foo.x() : map = true ? {} : {};
|
||||
// }
|
||||
BeginGroupToken begin = token.next;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
continue;
|
||||
}
|
||||
if (identical(nextValue, '<')) {
|
||||
// Handle cases like this:
|
||||
// class Foo {
|
||||
// var map;
|
||||
// Foo() : map = <String, Foo>{};
|
||||
// Foo.x() : map = true ? <String, Foo>{} : <String, Foo>{};
|
||||
// }
|
||||
BeginGroupToken begin = token.next;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
if (identical(token.stringValue, '{')) {
|
||||
begin = token;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
token = token.next;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!mayParseFunctionExpressions && identical(value, '{')) {
|
||||
break;
|
||||
}
|
||||
if (token is BeginGroupToken) {
|
||||
BeginGroupToken begin = token;
|
||||
token = (begin.endGroup != null) ? begin.endGroup : token;
|
||||
} else if (token is ErrorToken) {
|
||||
listener.reportErrorToken(token);
|
||||
}
|
||||
token = token.next;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token skipClassBody(Token token) {
|
||||
if (!optional('{', token)) {
|
||||
return listener.expectedClassBodyToSkip(token);
|
||||
}
|
||||
BeginGroupToken beginGroupToken = token;
|
||||
Token endGroup = beginGroupToken.endGroup;
|
||||
if (endGroup == null) {
|
||||
return listener.unmatched(beginGroupToken);
|
||||
} else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) {
|
||||
return listener.unmatched(beginGroupToken);
|
||||
}
|
||||
return endGroup;
|
||||
}
|
||||
|
||||
Token skipAsyncModifier(Token token) {
|
||||
String value = token.stringValue;
|
||||
if (identical(value, 'async')) {
|
||||
token = token.next;
|
||||
value = token.stringValue;
|
||||
|
||||
if (identical(value, '*')) {
|
||||
token = token.next;
|
||||
}
|
||||
} else if (identical(value, 'sync')) {
|
||||
token = token.next;
|
||||
value = token.stringValue;
|
||||
|
||||
if (identical(value, '*')) {
|
||||
token = token.next;
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
|
||||
assert(!isExpression);
|
||||
token = skipAsyncModifier(token);
|
||||
String value = token.stringValue;
|
||||
if (identical(value, ';')) {
|
||||
if (!allowAbstract) {
|
||||
listener.reportError(token, MessageKind.BODY_EXPECTED);
|
||||
}
|
||||
listener.handleNoFunctionBody(token);
|
||||
} else {
|
||||
if (identical(value, '=>')) {
|
||||
token = parseExpression(token.next);
|
||||
expectSemicolon(token);
|
||||
} else if (value == '=') {
|
||||
token = parseRedirectingFactoryBody(token);
|
||||
expectSemicolon(token);
|
||||
} else {
|
||||
token = skipBlock(token);
|
||||
}
|
||||
listener.skippedFunctionBody(token);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Token parseFormalParameters(Token token) => skipFormals(token);
|
||||
|
||||
Token skipFormals(Token token) {
|
||||
listener.beginOptionalFormalParameters(token);
|
||||
if (!optional('(', token)) {
|
||||
if (optional(';', token)) {
|
||||
listener.recoverableError(token, "expected '('");
|
||||
return token;
|
||||
}
|
||||
return listener.unexpected(token);
|
||||
}
|
||||
BeginGroupToken beginGroupToken = token;
|
||||
Token endToken = beginGroupToken.endGroup;
|
||||
listener.endFormalParameters(0, token, endToken);
|
||||
return endToken.next;
|
||||
}
|
||||
}
|
||||
|
|
72
pkg/front_end/lib/src/fasta/scanner.dart
Normal file
72
pkg/front_end/lib/src/fasta/scanner.dart
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.scanner;
|
||||
|
||||
import 'scanner/token.dart' show
|
||||
Token;
|
||||
|
||||
import 'scanner/utf8_bytes_scanner.dart' show
|
||||
Utf8BytesScanner;
|
||||
|
||||
import 'scanner/recover.dart' show
|
||||
defaultRecoveryStrategy;
|
||||
|
||||
export 'scanner/token.dart' show
|
||||
BeginGroupToken,
|
||||
ErrorToken,
|
||||
KeywordToken,
|
||||
StringToken,
|
||||
SymbolToken,
|
||||
Token,
|
||||
isBinaryOperator,
|
||||
isMinusOperator,
|
||||
isTernaryOperator,
|
||||
isUnaryOperator,
|
||||
isUserDefinableOperator;
|
||||
|
||||
export 'scanner/token_constants.dart' show
|
||||
EOF_TOKEN;
|
||||
|
||||
export 'scanner/utf8_bytes_scanner.dart' show
|
||||
Utf8BytesScanner;
|
||||
|
||||
export 'scanner/string_scanner.dart' show
|
||||
StringScanner;
|
||||
|
||||
export 'scanner/keyword.dart' show
|
||||
Keyword;
|
||||
|
||||
typedef Token Recover(List<int> bytes, Token tokens, List<int> lineStarts);
|
||||
|
||||
abstract class Scanner {
|
||||
/// Returns true if an error occured during [tokenize].
|
||||
bool get hasErrors;
|
||||
|
||||
List<int> get lineStarts;
|
||||
|
||||
Token tokenize();
|
||||
}
|
||||
|
||||
class ScannerResult {
|
||||
final Token tokens;
|
||||
final List<int> lineStarts;
|
||||
|
||||
ScannerResult(this.tokens, this.lineStarts);
|
||||
}
|
||||
|
||||
ScannerResult scan(List<int> bytes,
|
||||
{bool includeComments: false, Recover recover}) {
|
||||
if (bytes.last != 0) {
|
||||
throw new ArgumentError("[bytes]: the last byte must be null.");
|
||||
}
|
||||
Scanner scanner =
|
||||
new Utf8BytesScanner(bytes, includeComments: includeComments);
|
||||
Token tokens = scanner.tokenize();
|
||||
if (scanner.hasErrors) {
|
||||
recover ??= defaultRecoveryStrategy;
|
||||
tokens = recover(bytes, tokens, scanner.lineStarts);
|
||||
}
|
||||
return new ScannerResult(tokens, scanner.lineStarts);
|
||||
}
|
|
@ -2,33 +2,32 @@
|
|||
// 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 dart2js.scanner;
|
||||
library fasta.scanner.abstract_scanner;
|
||||
|
||||
import '../io/source_file.dart' show SourceFile, Utf8BytesSourceFile;
|
||||
import '../tokens/keyword.dart' show Keyword, KeywordState;
|
||||
import '../tokens/precedence.dart';
|
||||
import '../tokens/precedence_constants.dart';
|
||||
import '../tokens/token.dart';
|
||||
import '../tokens/token_constants.dart';
|
||||
import '../util/characters.dart';
|
||||
import 'string_scanner.dart' show StringScanner;
|
||||
import 'utf8_bytes_scanner.dart' show Utf8BytesScanner;
|
||||
import '../scanner.dart' show
|
||||
Scanner;
|
||||
|
||||
abstract class Scanner {
|
||||
Token tokenize();
|
||||
import 'keyword.dart' show
|
||||
KeywordState,
|
||||
Keyword;
|
||||
|
||||
factory Scanner(SourceFile file, {bool includeComments: false}) {
|
||||
if (file is Utf8BytesSourceFile) {
|
||||
return new Utf8BytesScanner(file, includeComments: includeComments);
|
||||
} else {
|
||||
return new StringScanner(file, includeComments: includeComments);
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'precedence.dart';
|
||||
|
||||
import 'token.dart' show
|
||||
BadInputToken,
|
||||
BeginGroupToken,
|
||||
ErrorToken,
|
||||
KeywordToken,
|
||||
SymbolToken,
|
||||
Token,
|
||||
UnmatchedToken,
|
||||
UnterminatedToken;
|
||||
|
||||
import 'token_constants.dart';
|
||||
|
||||
import 'characters.dart';
|
||||
|
||||
abstract class AbstractScanner implements Scanner {
|
||||
// TODO(ahe): Move this class to implementation.
|
||||
|
||||
final bool includeComments;
|
||||
|
||||
/**
|
||||
|
@ -54,16 +53,9 @@ abstract class AbstractScanner implements Scanner {
|
|||
*/
|
||||
Token tail;
|
||||
|
||||
/**
|
||||
* The source file that is being scanned. This field can be [:null:].
|
||||
* If the source file is available, the scanner assigns its [:lineStarts:] and
|
||||
* [:length:] fields at the end of [tokenize].
|
||||
*/
|
||||
final SourceFile file;
|
||||
|
||||
final List<int> lineStarts = <int>[0];
|
||||
|
||||
AbstractScanner(this.file, this.includeComments) {
|
||||
AbstractScanner(this.includeComments) {
|
||||
this.tail = this.tokens;
|
||||
}
|
||||
|
||||
|
@ -214,12 +206,8 @@ abstract class AbstractScanner implements Scanner {
|
|||
}
|
||||
}
|
||||
|
||||
if (file != null) {
|
||||
file.length = stringOffset;
|
||||
// One additional line start at the end, see [SourceFile.lineStarts].
|
||||
lineStarts.add(stringOffset + 1);
|
||||
file.lineStarts = lineStarts;
|
||||
}
|
||||
// Always pretend that there's a line at the end of the file.
|
||||
lineStarts.add(stringOffset + 1);
|
||||
|
||||
return firstToken();
|
||||
}
|
||||
|
@ -635,7 +623,6 @@ abstract class AbstractScanner implements Scanner {
|
|||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int tokenizeHexOrNumber(int next) {
|
||||
|
@ -665,7 +652,6 @@ abstract class AbstractScanner implements Scanner {
|
|||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int tokenizeDotsOrNumber(int next) {
|
||||
|
@ -761,7 +747,6 @@ abstract class AbstractScanner implements Scanner {
|
|||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int tokenizeMultiLineComment(int next, int start) {
|
||||
|
|
|
@ -2,24 +2,43 @@
|
|||
// 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 dart2js.scanner.array_based;
|
||||
library fasta.scanner.array_based_scanner;
|
||||
|
||||
import '../io/source_file.dart' show SourceFile;
|
||||
import '../tokens/keyword.dart' show Keyword;
|
||||
import '../tokens/precedence.dart' show PrecedenceInfo;
|
||||
import '../tokens/precedence_constants.dart' as Precedence
|
||||
show COMMENT_INFO, EOF_INFO;
|
||||
import '../tokens/token.dart'
|
||||
show BeginGroupToken, ErrorToken, KeywordToken, SymbolToken, Token;
|
||||
import '../tokens/token_constants.dart' as Tokens
|
||||
show LT_TOKEN, OPEN_CURLY_BRACKET_TOKEN, STRING_INTERPOLATION_TOKEN;
|
||||
import '../util/characters.dart' show $LF, $STX;
|
||||
import '../util/util.dart' show Link;
|
||||
import 'scanner.dart' show AbstractScanner;
|
||||
import 'keyword.dart' show
|
||||
Keyword;
|
||||
|
||||
import 'precedence.dart' show
|
||||
COMMENT_INFO,
|
||||
EOF_INFO,
|
||||
PrecedenceInfo;
|
||||
|
||||
import 'token.dart' show
|
||||
BeginGroupToken,
|
||||
ErrorToken,
|
||||
KeywordToken,
|
||||
SymbolToken,
|
||||
Token;
|
||||
|
||||
import 'token_constants.dart' show
|
||||
LT_TOKEN,
|
||||
OPEN_CURLY_BRACKET_TOKEN,
|
||||
STRING_INTERPOLATION_TOKEN;
|
||||
|
||||
import 'characters.dart' show
|
||||
$LF,
|
||||
$STX;
|
||||
|
||||
import 'abstract_scanner.dart' show
|
||||
AbstractScanner;
|
||||
|
||||
import 'package:front_end/src/fasta/util/link.dart' show
|
||||
Link;
|
||||
|
||||
abstract class ArrayBasedScanner extends AbstractScanner {
|
||||
ArrayBasedScanner(SourceFile file, bool includeComments)
|
||||
: super(file, includeComments);
|
||||
bool hasErrors = false;
|
||||
|
||||
ArrayBasedScanner(bool includeComments)
|
||||
: super(includeComments);
|
||||
|
||||
/**
|
||||
* The stack of open groups, e.g [: { ... ( .. :]
|
||||
|
@ -77,7 +96,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
unmatchedBeginGroup(groupingStack.head);
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
tail.next = new SymbolToken(Precedence.EOF_INFO, tokenStart);
|
||||
tail.next = new SymbolToken(EOF_INFO, tokenStart);
|
||||
tail = tail.next;
|
||||
// EOF points to itself so there's always infinite look-ahead.
|
||||
tail.next = tail;
|
||||
|
@ -91,7 +110,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
* [lineStarts] map.
|
||||
*/
|
||||
void appendWhiteSpace(int next) {
|
||||
if (next == $LF && file != null) {
|
||||
if (next == $LF) {
|
||||
lineStarts.add(stringOffset + 1); // +1, the line starts after the $LF.
|
||||
}
|
||||
}
|
||||
|
@ -103,9 +122,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
* [lineStarts] map.
|
||||
*/
|
||||
void lineFeedInMultiline() {
|
||||
if (file != null) {
|
||||
lineStarts.add(stringOffset + 1);
|
||||
}
|
||||
lineStarts.add(stringOffset + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,7 +135,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
tail = tail.next;
|
||||
|
||||
// { ( [ ${ cannot appear inside a type parameters / arguments.
|
||||
if (!identical(info.kind, Tokens.LT_TOKEN)) discardOpenLt();
|
||||
if (!identical(info.kind, LT_TOKEN)) discardOpenLt();
|
||||
groupingStack = groupingStack.prepend(token);
|
||||
}
|
||||
|
||||
|
@ -128,7 +145,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
* '>>' are handled separately bo [appendGt] and [appendGtGt].
|
||||
*/
|
||||
int appendEndGroup(PrecedenceInfo info, int openKind) {
|
||||
assert(!identical(openKind, Tokens.LT_TOKEN)); // openKind is < for > and >>
|
||||
assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
|
||||
discardBeginGroupUntil(openKind);
|
||||
appendPrecedenceToken(info);
|
||||
Token close = tail;
|
||||
|
@ -137,8 +154,8 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
}
|
||||
BeginGroupToken begin = groupingStack.head;
|
||||
if (!identical(begin.kind, openKind)) {
|
||||
assert(begin.kind == Tokens.STRING_INTERPOLATION_TOKEN &&
|
||||
openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN);
|
||||
assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
|
||||
openKind == OPEN_CURLY_BRACKET_TOKEN);
|
||||
// We're ending an interpolated expression.
|
||||
begin.endGroup = close;
|
||||
groupingStack = groupingStack.tail;
|
||||
|
@ -162,8 +179,8 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
if (groupingStack.isEmpty) return;
|
||||
BeginGroupToken begin = groupingStack.head;
|
||||
if (openKind == begin.kind) return;
|
||||
if (openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN &&
|
||||
begin.kind == Tokens.STRING_INTERPOLATION_TOKEN) return;
|
||||
if (openKind == OPEN_CURLY_BRACKET_TOKEN &&
|
||||
begin.kind == STRING_INTERPOLATION_TOKEN) return;
|
||||
unmatchedBeginGroup(begin);
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
|
@ -177,7 +194,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
void appendGt(PrecedenceInfo info) {
|
||||
appendPrecedenceToken(info);
|
||||
if (groupingStack.isEmpty) return;
|
||||
if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
|
||||
if (identical(groupingStack.head.kind, LT_TOKEN)) {
|
||||
groupingStack.head.endGroup = tail;
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
|
@ -191,13 +208,13 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
void appendGtGt(PrecedenceInfo info) {
|
||||
appendPrecedenceToken(info);
|
||||
if (groupingStack.isEmpty) return;
|
||||
if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
|
||||
if (identical(groupingStack.head.kind, LT_TOKEN)) {
|
||||
// Don't assign endGroup: in "T<U<V>>", the '>>' token closes the outer
|
||||
// '<', the inner '<' is left without endGroup.
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
if (groupingStack.isEmpty) return;
|
||||
if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
|
||||
if (identical(groupingStack.head.kind, LT_TOKEN)) {
|
||||
groupingStack.head.endGroup = tail;
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
|
@ -205,10 +222,11 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
|
||||
void appendComment(start, bool asciiOnly) {
|
||||
if (!includeComments) return;
|
||||
appendSubstringToken(Precedence.COMMENT_INFO, start, asciiOnly);
|
||||
appendSubstringToken(COMMENT_INFO, start, asciiOnly);
|
||||
}
|
||||
|
||||
void appendErrorToken(ErrorToken token) {
|
||||
hasErrors = true;
|
||||
tail.next = token;
|
||||
tail = token;
|
||||
}
|
||||
|
@ -226,7 +244,7 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|||
*/
|
||||
void discardOpenLt() {
|
||||
while (!groupingStack.isEmpty &&
|
||||
identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
|
||||
identical(groupingStack.head.kind, LT_TOKEN)) {
|
||||
groupingStack = groupingStack.tail;
|
||||
}
|
||||
}
|
||||
|
|
7
pkg/front_end/lib/src/fasta/scanner/bin/scanner.dart
Normal file
7
pkg/front_end/lib/src/fasta/scanner/bin/scanner.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
// 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.md file.
|
||||
|
||||
import 'package:front_end/src/fasta/scanner/main.dart' as dart_scanner;
|
||||
|
||||
main(List<String> arguments) => dart_scanner.main(arguments);
|
|
@ -2,7 +2,7 @@
|
|||
// 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 characters;
|
||||
library fasta.scanner.characters;
|
||||
|
||||
const int $EOF = 0;
|
||||
const int $STX = 2;
|
||||
|
|
|
@ -1,408 +1,46 @@
|
|||
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
// BSD-style license that can be found in the LICENSE.md file.
|
||||
|
||||
library source_file_provider;
|
||||
library fasta.scanner.io;
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
import 'dart:typed_data';
|
||||
import 'dart:async' show
|
||||
Future;
|
||||
|
||||
import '../compiler.dart' as api show Diagnostic;
|
||||
import '../compiler_new.dart' as api;
|
||||
import '../compiler_new.dart';
|
||||
import 'colors.dart' as colors;
|
||||
import 'dart2js.dart' show AbortLeg;
|
||||
import 'filenames.dart';
|
||||
import 'io/source_file.dart';
|
||||
import 'util/uri_extras.dart';
|
||||
import 'dart:io' show
|
||||
File,
|
||||
RandomAccessFile;
|
||||
|
||||
abstract class SourceFileProvider implements CompilerInput {
|
||||
bool isWindows = (Platform.operatingSystem == 'windows');
|
||||
Uri cwd = currentDirectory;
|
||||
Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{};
|
||||
int dartCharactersRead = 0;
|
||||
import 'dart:typed_data' show
|
||||
Uint8List;
|
||||
|
||||
Future<String> readStringFromUri(Uri resourceUri) {
|
||||
return readUtf8BytesFromUri(resourceUri).then(UTF8.decode);
|
||||
}
|
||||
|
||||
Future<List<int>> readUtf8BytesFromUri(Uri resourceUri) {
|
||||
if (resourceUri.scheme == 'file') {
|
||||
return _readFromFile(resourceUri);
|
||||
} else if (resourceUri.scheme == 'http' || resourceUri.scheme == 'https') {
|
||||
return _readFromHttp(resourceUri);
|
||||
} else {
|
||||
throw new ArgumentError("Unknown scheme in uri '$resourceUri'");
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<int>> _readFromFile(Uri resourceUri) {
|
||||
assert(resourceUri.scheme == 'file');
|
||||
List<int> source;
|
||||
try {
|
||||
source = readAll(resourceUri.toFilePath());
|
||||
} on FileSystemException catch (ex) {
|
||||
String message = ex.osError?.message;
|
||||
String detail = message != null ? ' ($message)' : '';
|
||||
return new Future.error(
|
||||
"Error reading '${relativizeUri(resourceUri)}' $detail");
|
||||
}
|
||||
dartCharactersRead += source.length;
|
||||
sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile(
|
||||
resourceUri, relativizeUri(resourceUri), source);
|
||||
return new Future.value(source);
|
||||
}
|
||||
|
||||
Future<List<int>> _readFromHttp(Uri resourceUri) {
|
||||
assert(resourceUri.scheme == 'http');
|
||||
HttpClient client = new HttpClient();
|
||||
return client
|
||||
.getUrl(resourceUri)
|
||||
.then((HttpClientRequest request) => request.close())
|
||||
.then((HttpClientResponse response) {
|
||||
if (response.statusCode != HttpStatus.OK) {
|
||||
String msg = 'Failure getting $resourceUri: '
|
||||
'${response.statusCode} ${response.reasonPhrase}';
|
||||
throw msg;
|
||||
}
|
||||
return response.toList();
|
||||
}).then((List<List<int>> splitContent) {
|
||||
int totalLength = splitContent.fold(0, (int old, List list) {
|
||||
return old + list.length;
|
||||
});
|
||||
Uint8List result = new Uint8List(totalLength);
|
||||
int offset = 0;
|
||||
for (List<int> contentPart in splitContent) {
|
||||
result.setRange(offset, offset + contentPart.length, contentPart);
|
||||
offset += contentPart.length;
|
||||
}
|
||||
dartCharactersRead += totalLength;
|
||||
sourceFiles[resourceUri] = new CachingUtf8BytesSourceFile(
|
||||
resourceUri, resourceUri.toString(), result);
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
|
||||
// API.
|
||||
Future/*<List<int> | String>*/ call(Uri resourceUri) => throw "unimplemented";
|
||||
|
||||
relativizeUri(Uri uri) => relativize(cwd, uri, isWindows);
|
||||
|
||||
SourceFile getSourceFile(Uri resourceUri) {
|
||||
return sourceFiles[resourceUri];
|
||||
List<int> readBytesFromFileSync(Uri uri) {
|
||||
RandomAccessFile file = new File.fromUri(uri).openSync();
|
||||
Uint8List list;
|
||||
try {
|
||||
int length = file.lengthSync();
|
||||
// +1 to have a 0 terminated list, see [Scanner].
|
||||
list = new Uint8List(length + 1);
|
||||
file.readIntoSync(list, 0, length);
|
||||
} finally {
|
||||
file.closeSync();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
List<int> readAll(String filename) {
|
||||
var file = (new File(filename)).openSync();
|
||||
var length = file.lengthSync();
|
||||
// +1 to have a 0 terminated list, see [Scanner].
|
||||
var buffer = new Uint8List(length + 1);
|
||||
file.readIntoSync(buffer, 0, length);
|
||||
file.closeSync();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
class CompilerSourceFileProvider extends SourceFileProvider {
|
||||
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
|
||||
// API.
|
||||
Future<List<int>> call(Uri resourceUri) => readFromUri(resourceUri);
|
||||
|
||||
@override
|
||||
Future readFromUri(Uri uri) => readUtf8BytesFromUri(uri);
|
||||
}
|
||||
|
||||
class FormattingDiagnosticHandler implements CompilerDiagnostics {
|
||||
final SourceFileProvider provider;
|
||||
bool showWarnings = true;
|
||||
bool showHints = true;
|
||||
bool verbose = false;
|
||||
bool isAborting = false;
|
||||
bool enableColors = false;
|
||||
bool throwOnError = false;
|
||||
int throwOnErrorCount = 0;
|
||||
api.Diagnostic lastKind = null;
|
||||
int fatalCount = 0;
|
||||
|
||||
final int FATAL = api.Diagnostic.CRASH.ordinal | api.Diagnostic.ERROR.ordinal;
|
||||
final int INFO =
|
||||
api.Diagnostic.INFO.ordinal | api.Diagnostic.VERBOSE_INFO.ordinal;
|
||||
|
||||
FormattingDiagnosticHandler([SourceFileProvider provider])
|
||||
: this.provider =
|
||||
(provider == null) ? new CompilerSourceFileProvider() : provider;
|
||||
|
||||
void info(var message, [api.Diagnostic kind = api.Diagnostic.VERBOSE_INFO]) {
|
||||
if (!verbose && kind == api.Diagnostic.VERBOSE_INFO) return;
|
||||
if (enableColors) {
|
||||
print('${colors.green("Info:")} $message');
|
||||
} else {
|
||||
print('Info: $message');
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds [kind] specific prefix to [message].
|
||||
String prefixMessage(String message, api.Diagnostic kind) {
|
||||
switch (kind) {
|
||||
case api.Diagnostic.ERROR:
|
||||
return 'Error: $message';
|
||||
case api.Diagnostic.WARNING:
|
||||
return 'Warning: $message';
|
||||
case api.Diagnostic.HINT:
|
||||
return 'Hint: $message';
|
||||
case api.Diagnostic.CRASH:
|
||||
return 'Internal Error: $message';
|
||||
case api.Diagnostic.INFO:
|
||||
case api.Diagnostic.VERBOSE_INFO:
|
||||
return 'Info: $message';
|
||||
}
|
||||
throw 'Unexpected diagnostic kind: $kind (${kind.ordinal})';
|
||||
}
|
||||
|
||||
@override
|
||||
void report(var code, Uri uri, int begin, int end, String message,
|
||||
api.Diagnostic kind) {
|
||||
if (isAborting) return;
|
||||
isAborting = (kind == api.Diagnostic.CRASH);
|
||||
|
||||
bool fatal = (kind.ordinal & FATAL) != 0;
|
||||
bool isInfo = (kind.ordinal & INFO) != 0;
|
||||
if (isInfo && uri == null && kind != api.Diagnostic.INFO) {
|
||||
info(message, kind);
|
||||
return;
|
||||
}
|
||||
|
||||
message = prefixMessage(message, kind);
|
||||
|
||||
// [lastKind] records the previous non-INFO kind we saw.
|
||||
// This is used to suppress info about a warning when warnings are
|
||||
// suppressed, and similar for hints.
|
||||
if (kind != api.Diagnostic.INFO) {
|
||||
lastKind = kind;
|
||||
}
|
||||
var color;
|
||||
if (kind == api.Diagnostic.ERROR) {
|
||||
color = colors.red;
|
||||
} else if (kind == api.Diagnostic.WARNING) {
|
||||
if (!showWarnings) return;
|
||||
color = colors.magenta;
|
||||
} else if (kind == api.Diagnostic.HINT) {
|
||||
if (!showHints) return;
|
||||
color = colors.cyan;
|
||||
} else if (kind == api.Diagnostic.CRASH) {
|
||||
color = colors.red;
|
||||
} else if (kind == api.Diagnostic.INFO) {
|
||||
if (lastKind == api.Diagnostic.WARNING && !showWarnings) return;
|
||||
if (lastKind == api.Diagnostic.HINT && !showHints) return;
|
||||
color = colors.green;
|
||||
} else {
|
||||
throw 'Unknown kind: $kind (${kind.ordinal})';
|
||||
}
|
||||
if (!enableColors) {
|
||||
color = (x) => x;
|
||||
}
|
||||
if (uri == null) {
|
||||
print('${color(message)}');
|
||||
} else {
|
||||
SourceFile file = provider.sourceFiles[uri];
|
||||
if (file != null) {
|
||||
print(file.getLocationMessage(color(message), begin, end,
|
||||
colorize: color));
|
||||
} else {
|
||||
String position = end - begin > 0 ? '@$begin+${end - begin}' : '';
|
||||
print('${provider.relativizeUri(uri)}$position:\n'
|
||||
'${color(message)}');
|
||||
}
|
||||
}
|
||||
if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
|
||||
isAborting = true;
|
||||
throw new AbortLeg(message);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(johnniwinther): Remove this when no longer needed for the old compiler
|
||||
// API.
|
||||
void call(Uri uri, int begin, int end, String message, api.Diagnostic kind) {
|
||||
return report(null, uri, begin, end, message, kind);
|
||||
}
|
||||
}
|
||||
|
||||
typedef void MessageCallback(String message);
|
||||
|
||||
class RandomAccessFileOutputProvider implements CompilerOutput {
|
||||
final Uri out;
|
||||
final Uri sourceMapOut;
|
||||
final Uri resolutionOutput;
|
||||
final MessageCallback onInfo;
|
||||
final MessageCallback onFailure;
|
||||
|
||||
int totalCharactersWritten = 0;
|
||||
List<String> allOutputFiles = new List<String>();
|
||||
|
||||
RandomAccessFileOutputProvider(this.out, this.sourceMapOut,
|
||||
{this.onInfo, this.onFailure, this.resolutionOutput});
|
||||
|
||||
static Uri computePrecompiledUri(Uri out) {
|
||||
String extension = 'precompiled.js';
|
||||
String outPath = out.path;
|
||||
if (outPath.endsWith('.js')) {
|
||||
outPath = outPath.substring(0, outPath.length - 3);
|
||||
return out.resolve('$outPath.$extension');
|
||||
} else {
|
||||
return out.resolve(extension);
|
||||
}
|
||||
}
|
||||
|
||||
EventSink<String> call(String name, String extension) {
|
||||
return createEventSink(name, extension);
|
||||
}
|
||||
|
||||
EventSink<String> createEventSink(String name, String extension) {
|
||||
Uri uri;
|
||||
bool isPrimaryOutput = false;
|
||||
// TODO (johnniwinther, sigurdm): Make a better interface for
|
||||
// output-providers.
|
||||
if (extension == "deferred_map") {
|
||||
uri = out.resolve(name);
|
||||
} else if (name == '') {
|
||||
if (extension == 'js' || extension == 'dart') {
|
||||
isPrimaryOutput = true;
|
||||
uri = out;
|
||||
} else if (extension == 'precompiled.js') {
|
||||
uri = computePrecompiledUri(out);
|
||||
onInfo("File ($uri) is compatible with header"
|
||||
" \"Content-Security-Policy: script-src 'self'\"");
|
||||
} else if (extension == 'js.map' || extension == 'dart.map') {
|
||||
uri = sourceMapOut;
|
||||
} else if (extension == 'info.json') {
|
||||
String outName = out.path.substring(out.path.lastIndexOf('/') + 1);
|
||||
uri = out.resolve('$outName.$extension');
|
||||
} else if (extension == 'data') {
|
||||
if (resolutionOutput == null) {
|
||||
onFailure('Serialization target unspecified.');
|
||||
}
|
||||
uri = resolutionOutput;
|
||||
} else {
|
||||
onFailure('Unknown extension: $extension');
|
||||
}
|
||||
} else {
|
||||
uri = out.resolve('$name.$extension');
|
||||
}
|
||||
|
||||
if (uri.scheme != 'file') {
|
||||
onFailure('Unhandled scheme ${uri.scheme} in $uri.');
|
||||
}
|
||||
|
||||
RandomAccessFile output;
|
||||
try {
|
||||
output = new File(uri.toFilePath()).openSync(mode: FileMode.WRITE);
|
||||
} on FileSystemException catch (e) {
|
||||
onFailure('$e');
|
||||
}
|
||||
|
||||
allOutputFiles.add(relativize(currentDirectory, uri, Platform.isWindows));
|
||||
|
||||
int charactersWritten = 0;
|
||||
|
||||
writeStringSync(String data) {
|
||||
// Write the data in chunks of 8kb, otherwise we risk running OOM.
|
||||
int chunkSize = 8 * 1024;
|
||||
|
||||
int offset = 0;
|
||||
while (offset < data.length) {
|
||||
output.writeStringSync(
|
||||
data.substring(offset, math.min(offset + chunkSize, data.length)));
|
||||
offset += chunkSize;
|
||||
}
|
||||
charactersWritten += data.length;
|
||||
}
|
||||
|
||||
onDone() {
|
||||
output.closeSync();
|
||||
if (isPrimaryOutput) {
|
||||
totalCharactersWritten += charactersWritten;
|
||||
}
|
||||
}
|
||||
|
||||
return new _EventSinkWrapper(writeStringSync, onDone);
|
||||
}
|
||||
}
|
||||
|
||||
class _EventSinkWrapper extends EventSink<String> {
|
||||
var onAdd, onClose;
|
||||
|
||||
_EventSinkWrapper(this.onAdd, this.onClose);
|
||||
|
||||
void add(String data) => onAdd(data);
|
||||
|
||||
void addError(error, [StackTrace stackTrace]) => throw error;
|
||||
|
||||
void close() => onClose();
|
||||
}
|
||||
|
||||
/// Adapter to integrate dart2js in bazel.
|
||||
///
|
||||
/// To handle bazel's special layout:
|
||||
///
|
||||
/// * We specify a .packages configuration file that expands packages to their
|
||||
/// corresponding bazel location. This way there is no need to create a pub
|
||||
/// cache prior to invoking dart2js.
|
||||
///
|
||||
/// * We provide an implicit mapping that can make all urls relative to the
|
||||
/// bazel root.
|
||||
/// To the compiler, URIs look like:
|
||||
/// file:///bazel-root/a/b/c.dart
|
||||
///
|
||||
/// even though in the file system the file is located at:
|
||||
/// file:///path/to/the/actual/bazel/root/a/b/c.dart
|
||||
///
|
||||
/// This mapping serves two purposes:
|
||||
/// - It makes compiler results independent of the machine layout, which
|
||||
/// enables us to share results across bazel runs and across machines.
|
||||
///
|
||||
/// - It hides the distinction between generated and source files. That way
|
||||
/// we can use the standard package-resolution mechanism and ignore the
|
||||
/// internals of how files are organized within bazel.
|
||||
///
|
||||
/// When invoking the compiler, bazel will use `package:` and
|
||||
/// `file:///bazel-root/` URIs to specify entrypoints.
|
||||
///
|
||||
/// The mapping is specified using search paths relative to the current
|
||||
/// directory. When this provider looks up a file, the bazel-root folder is
|
||||
/// replaced by the first directory in the search path containing the file, if
|
||||
/// any. For example, given the search path ".,bazel-bin/", and a URL
|
||||
/// of the form `file:///bazel-root/a/b.dart`, this provider will check if the
|
||||
/// file exists under "./a/b.dart", then check under "bazel-bin/a/b.dart". If
|
||||
/// none of the paths matches, it will attempt to load the file from
|
||||
/// `/bazel-root/a/b.dart` which will likely fail.
|
||||
class BazelInputProvider extends SourceFileProvider {
|
||||
final List<Uri> dirs;
|
||||
|
||||
BazelInputProvider(List<String> searchPaths)
|
||||
: dirs = searchPaths.map(_resolve).toList();
|
||||
|
||||
static _resolve(String path) => currentDirectory.resolve(path);
|
||||
|
||||
@override
|
||||
Future readFromUri(Uri uri) async {
|
||||
var resolvedUri = uri;
|
||||
var path = uri.path;
|
||||
if (path.startsWith('/bazel-root')) {
|
||||
path = path.substring('/bazel-root/'.length);
|
||||
for (var dir in dirs) {
|
||||
var file = dir.resolve(path);
|
||||
if (await new File.fromUri(file).exists()) {
|
||||
resolvedUri = file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
var result = await readUtf8BytesFromUri(resolvedUri);
|
||||
sourceFiles[uri] = sourceFiles[resolvedUri];
|
||||
return result;
|
||||
}
|
||||
Future<List<int>> readBytesFromFile(Uri uri) async {
|
||||
RandomAccessFile file = await new File.fromUri(uri).open();
|
||||
Uint8List list;
|
||||
try {
|
||||
int length = await file.length();
|
||||
// +1 to have a 0 terminated list, see [Scanner].
|
||||
list = new Uint8List(length + 1);
|
||||
int read = await file.readInto(list);
|
||||
if (read != length) {
|
||||
throw "Error reading file: ${uri}";
|
||||
}
|
||||
} finally {
|
||||
await file.close();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
// 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 dart2js.tokens.keywords;
|
||||
library fasta.scanner.keywords;
|
||||
|
||||
import '../util/characters.dart' as Characters show $a;
|
||||
import 'precedence.dart' show PrecedenceInfo;
|
||||
import 'precedence_constants.dart' as Precedence
|
||||
show AS_INFO, IS_INFO, KEYWORD_INFO;
|
||||
import 'characters.dart' show
|
||||
$a;
|
||||
|
||||
import 'precedence.dart' show
|
||||
PrecedenceInfo;
|
||||
|
||||
import 'precedence.dart' show
|
||||
AS_INFO,
|
||||
IS_INFO,
|
||||
KEYWORD_INFO;
|
||||
|
||||
/**
|
||||
* A keyword in the Dart programming language.
|
||||
|
@ -49,10 +55,10 @@ class Keyword {
|
|||
|
||||
// TODO(ahe): Don't think this is a reserved word.
|
||||
// See: http://dartbug.com/5579
|
||||
const Keyword("is", info: Precedence.IS_INFO),
|
||||
const Keyword("is", info: IS_INFO),
|
||||
|
||||
const Keyword("abstract", isBuiltIn: true),
|
||||
const Keyword("as", info: Precedence.AS_INFO, isBuiltIn: true),
|
||||
const Keyword("as", info: AS_INFO, isBuiltIn: true),
|
||||
const Keyword("covariant", isBuiltIn: true),
|
||||
const Keyword("dynamic", isBuiltIn: true),
|
||||
const Keyword("export", isBuiltIn: true),
|
||||
|
@ -97,7 +103,7 @@ class Keyword {
|
|||
const Keyword(this.syntax,
|
||||
{this.isPseudo: false,
|
||||
this.isBuiltIn: false,
|
||||
this.info: Precedence.KEYWORD_INFO});
|
||||
this.info: KEYWORD_INFO});
|
||||
|
||||
static Map<String, Keyword> computeKeywordMap() {
|
||||
Map<String, Keyword> result = new Map<String, Keyword>();
|
||||
|
@ -147,8 +153,8 @@ abstract class KeywordState {
|
|||
int c = strings[i].codeUnitAt(start);
|
||||
if (chunk != c) {
|
||||
if (chunkStart != -1) {
|
||||
assert(result[chunk - Characters.$a] == null);
|
||||
result[chunk - Characters.$a] = computeKeywordStateTable(
|
||||
assert(result[chunk - $a] == null);
|
||||
result[chunk - $a] = computeKeywordStateTable(
|
||||
start + 1, strings, chunkStart, i - chunkStart);
|
||||
}
|
||||
chunkStart = i;
|
||||
|
@ -157,8 +163,8 @@ abstract class KeywordState {
|
|||
}
|
||||
}
|
||||
if (chunkStart != -1) {
|
||||
assert(result[chunk - Characters.$a] == null);
|
||||
result[chunk - Characters.$a] = computeKeywordStateTable(
|
||||
assert(result[chunk - $a] == null);
|
||||
result[chunk - $a] = computeKeywordStateTable(
|
||||
start + 1, strings, chunkStart, offset + length - chunkStart);
|
||||
} else {
|
||||
assert(length == 1);
|
||||
|
@ -181,7 +187,7 @@ class ArrayKeywordState extends KeywordState {
|
|||
ArrayKeywordState(List<KeywordState> this.table, String syntax)
|
||||
: super((syntax == null) ? null : Keyword.keywords[syntax]);
|
||||
|
||||
KeywordState next(int c) => table[c - Characters.$a];
|
||||
KeywordState next(int c) => table[c - $a];
|
||||
|
||||
String toString() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
@ -194,7 +200,7 @@ class ArrayKeywordState extends KeywordState {
|
|||
List<KeywordState> foo = table;
|
||||
for (int i = 0; i < foo.length; i++) {
|
||||
if (foo[i] != null) {
|
||||
sb.write("${new String.fromCharCodes([i + Characters.$a])}: "
|
||||
sb.write("${new String.fromCharCodes([i + $a])}: "
|
||||
"${foo[i]}; ");
|
||||
}
|
||||
}
|
||||
|
|
36
pkg/front_end/lib/src/fasta/scanner/main.dart
Normal file
36
pkg/front_end/lib/src/fasta/scanner/main.dart
Normal file
|
@ -0,0 +1,36 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.scanner.main;
|
||||
|
||||
import 'io.dart' show
|
||||
readBytesFromFileSync;
|
||||
|
||||
import '../scanner.dart' show
|
||||
scan;
|
||||
|
||||
scanAll(Map<Uri, List<int>> files) {
|
||||
Stopwatch sw = new Stopwatch()..start();
|
||||
int byteCount = 0;
|
||||
files.forEach((Uri uri, List<int> bytes) {
|
||||
scan(bytes);
|
||||
byteCount += bytes.length - 1;
|
||||
});
|
||||
sw.stop();
|
||||
print("Scanning files took: ${sw.elapsed}");
|
||||
print("Bytes/ms: ${byteCount/sw.elapsedMilliseconds}");
|
||||
}
|
||||
|
||||
main(List<String> arguments) {
|
||||
Map<Uri, List<int>> files = <Uri, List<int>>{};
|
||||
Stopwatch sw = new Stopwatch()..start();
|
||||
for (String name in arguments) {
|
||||
Uri uri = Uri.base.resolve(name);
|
||||
List<int> bytes = readBytesFromFileSync(uri);
|
||||
files[uri] = bytes;
|
||||
}
|
||||
sw.stop();
|
||||
print("Reading files took: ${sw.elapsed}");
|
||||
scanAll(files);
|
||||
}
|
|
@ -2,11 +2,20 @@
|
|||
// 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 dart2js.tokens.precedence.constants;
|
||||
library fasta.scanner.precedence;
|
||||
|
||||
import 'precedence.dart' show PrecedenceInfo;
|
||||
import 'token_constants.dart';
|
||||
|
||||
class PrecedenceInfo {
|
||||
final String value;
|
||||
final int precedence;
|
||||
final int kind;
|
||||
|
||||
const PrecedenceInfo(this.value, this.precedence, this.kind);
|
||||
|
||||
toString() => 'PrecedenceInfo($value, $precedence, $kind)';
|
||||
}
|
||||
|
||||
// TODO(ahe): The following are not tokens in Dart.
|
||||
const PrecedenceInfo BACKPING_INFO =
|
||||
const PrecedenceInfo('`', 0, BACKPING_TOKEN);
|
||||
|
|
29
pkg/front_end/lib/src/fasta/scanner/recover.dart
Normal file
29
pkg/front_end/lib/src/fasta/scanner/recover.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2017, 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 licenset hat can be found in the LICENSE file.
|
||||
|
||||
library fasta.scanner.recover;
|
||||
|
||||
import 'token.dart' show
|
||||
Token;
|
||||
|
||||
/// Recover from errors in [tokens]. The original sources are provided as
|
||||
/// [bytes]. [lineStarts] are the beginning character offsets of lines, and
|
||||
/// must be updated if recovery is performed rewriting the original source
|
||||
/// code.
|
||||
Token defaultRecoveryStrategy(
|
||||
List<int> bytes, Token tokens, List<int> lineStarts) {
|
||||
// See [Parser.reportErrorToken](package:front_end/src/fasta/parser/src/parser.dart) for how
|
||||
// it currently handles lexical errors. In addition, notice how the parser
|
||||
// calls [handleInvalidExpression], [handleInvalidFunctionBody], and
|
||||
// [handleInvalidTypeReference] to allow the listener to recover its internal
|
||||
// state. See [package:compiler/src/parser/element_listener.dart] for an
|
||||
// example of how these events are used.
|
||||
//
|
||||
// In addition, the scanner will attempt a bit of recovery when braces don't
|
||||
// match up during brace grouping. See
|
||||
// [ArrayBasedScanner.discardBeginGroupUntil](array_based_scanner.dart). For
|
||||
// more details on brace grouping see
|
||||
// [AbstractScanner.unmatchedBeginGroup](abstract_scanner.dart).
|
||||
return tokens;
|
||||
}
|
|
@ -2,12 +2,17 @@
|
|||
// 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 dart2js.scanner.string;
|
||||
library dart2js.scanner.string_scanner;
|
||||
|
||||
import '../io/source_file.dart' show SourceFile;
|
||||
import '../tokens/precedence.dart' show PrecedenceInfo;
|
||||
import '../tokens/token.dart' show StringToken, Token;
|
||||
import 'array_based_scanner.dart' show ArrayBasedScanner;
|
||||
import 'array_based_scanner.dart' show
|
||||
ArrayBasedScanner;
|
||||
|
||||
import 'precedence.dart' show
|
||||
PrecedenceInfo;
|
||||
|
||||
import 'token.dart' show
|
||||
StringToken,
|
||||
Token;
|
||||
|
||||
/**
|
||||
* Scanner that reads from a String and creates tokens that points to
|
||||
|
@ -20,22 +25,15 @@ class StringScanner extends ArrayBasedScanner {
|
|||
/** The current offset in [string]. */
|
||||
int scanOffset = -1;
|
||||
|
||||
StringScanner(SourceFile file, {bool includeComments: false})
|
||||
: string = file.slowText(),
|
||||
super(file, includeComments) {
|
||||
ensureZeroTermination();
|
||||
}
|
||||
StringScanner(String string, {bool includeComments: false})
|
||||
: string = ensureZeroTermination(string),
|
||||
super(includeComments);
|
||||
|
||||
StringScanner.fromString(this.string, {bool includeComments: false})
|
||||
: super(null, includeComments) {
|
||||
ensureZeroTermination();
|
||||
}
|
||||
|
||||
void ensureZeroTermination() {
|
||||
if (string.isEmpty || string.codeUnitAt(string.length - 1) != 0) {
|
||||
// TODO(lry): abort instead of copying the array, or warn?
|
||||
string = string + '\x00';
|
||||
}
|
||||
static String ensureZeroTermination(String string) {
|
||||
return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
|
||||
// TODO(lry): abort instead of copying the array, or warn?
|
||||
? string + '\x00'
|
||||
: string;
|
||||
}
|
||||
|
||||
int advance() => string.codeUnitAt(++scanOffset);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// 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.md file.
|
||||
|
||||
library fasta.scanner.testing.scanner_chain;
|
||||
|
||||
import 'package:testing/testing.dart';
|
||||
|
||||
import 'package:front_end/src/fasta/scanner.dart';
|
||||
|
||||
import 'package:front_end/src/fasta/scanner/io.dart';
|
||||
|
||||
class Read extends Step<TestDescription, List<int>, ChainContext> {
|
||||
const Read();
|
||||
|
||||
String get name => "read";
|
||||
|
||||
Future<Result<List<int>>> run(
|
||||
TestDescription input, ChainContext context) async {
|
||||
return pass(await readBytesFromFile(input.uri));
|
||||
}
|
||||
}
|
||||
|
||||
class Scan extends Step<List<int>, ScannerResult, ChainContext> {
|
||||
const Scan();
|
||||
|
||||
String get name => "scan";
|
||||
|
||||
Future<Result<ScannerResult>> run(
|
||||
List<int> bytes, ChainContext context) async {
|
||||
return pass(scan(bytes));
|
||||
}
|
||||
}
|
|
@ -2,22 +2,28 @@
|
|||
// 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 dart2js.tokens;
|
||||
library fasta.scanner.token;
|
||||
|
||||
import 'dart:collection' show HashSet;
|
||||
import 'dart:convert' show UTF8;
|
||||
import 'dart:collection' show
|
||||
HashSet;
|
||||
|
||||
import '../common.dart';
|
||||
import '../util/util.dart' show computeHashCode;
|
||||
import 'keyword.dart' show Keyword;
|
||||
import 'precedence.dart' show PrecedenceInfo;
|
||||
import 'precedence_constants.dart' as Precedence show BAD_INPUT_INFO;
|
||||
import 'token_constants.dart' as Tokens show IDENTIFIER_TOKEN;
|
||||
import 'dart:convert' show
|
||||
UTF8;
|
||||
|
||||
import 'keyword.dart' show
|
||||
Keyword;
|
||||
|
||||
import 'precedence.dart' show
|
||||
BAD_INPUT_INFO,
|
||||
PrecedenceInfo;
|
||||
|
||||
import 'token_constants.dart' show
|
||||
IDENTIFIER_TOKEN;
|
||||
|
||||
/**
|
||||
* A token that doubles as a linked list.
|
||||
*/
|
||||
abstract class Token implements Spannable {
|
||||
abstract class Token {
|
||||
/**
|
||||
* The character offset of the start of this token within the source text.
|
||||
*/
|
||||
|
@ -95,7 +101,7 @@ abstract class Token implements Spannable {
|
|||
* The number of characters parsed by this token.
|
||||
*/
|
||||
int get charCount {
|
||||
if (info == Precedence.BAD_INPUT_INFO) {
|
||||
if (info == BAD_INPUT_INFO) {
|
||||
// This is a token that wraps around an error message. Return 1
|
||||
// instead of the size of the length of the error message.
|
||||
return 1;
|
||||
|
@ -106,17 +112,6 @@ abstract class Token implements Spannable {
|
|||
|
||||
/// The character offset of the end of this token within the source text.
|
||||
int get charEnd => charOffset + charCount;
|
||||
|
||||
int get hashCode => computeHashCode(charOffset, info, value);
|
||||
}
|
||||
|
||||
/// A pair of tokens marking the beginning and the end of a span. Use for error
|
||||
/// reporting.
|
||||
class TokenPair implements Spannable {
|
||||
final Token begin;
|
||||
final Token end;
|
||||
|
||||
TokenPair(this.begin, this.end);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -172,10 +167,10 @@ class KeywordToken extends Token {
|
|||
abstract class ErrorToken extends Token {
|
||||
ErrorToken(int charOffset) : super(charOffset);
|
||||
|
||||
PrecedenceInfo get info => Precedence.BAD_INPUT_INFO;
|
||||
PrecedenceInfo get info => BAD_INPUT_INFO;
|
||||
|
||||
String get value {
|
||||
throw new SpannableAssertionFailure(this, assertionMessage);
|
||||
throw assertionMessage;
|
||||
}
|
||||
|
||||
String get stringValue => null;
|
||||
|
@ -307,7 +302,7 @@ class StringToken extends Token {
|
|||
/// See [Token.stringValue] for an explanation.
|
||||
String get stringValue => null;
|
||||
|
||||
bool isIdentifier() => identical(kind, Tokens.IDENTIFIER_TOKEN);
|
||||
bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN);
|
||||
|
||||
String toString() => "StringToken($value)";
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
// 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 dart2js.tokens.constants;
|
||||
library fasta.scanner.token_constants;
|
||||
|
||||
import '../util/characters.dart';
|
||||
import 'characters.dart';
|
||||
|
||||
const int EOF_TOKEN = 0;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue