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

Side by Side Diff: lib/compiler/implementation/scanner/scanner_task.dart

Issue 10990060: Added support for exports and re-exports. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed redundant check. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 class ScannerTask extends CompilerTask { 5 class ScannerTask extends CompilerTask {
6 ScannerTask(Compiler compiler) : super(compiler); 6 ScannerTask(Compiler compiler) : super(compiler);
7 String get name => 'Scanner'; 7 String get name => 'Scanner';
8 8
9 void scanLibrary(LibraryElement library) { 9 /**
10 * Scans [library] and registers the declared top level entities to [handler]
11 * for the computation of the library export scope.
12 */
13 void scanLibrary(ImportExportHandler handler, LibraryElement library) {
10 var compilationUnit = library.entryCompilationUnit; 14 var compilationUnit = library.entryCompilationUnit;
11 compiler.log("scanning library ${compilationUnit.script.name}"); 15 compiler.log("scanning library ${compilationUnit.script.name}");
12 scan(compilationUnit); 16 scan(compilationUnit);
13 processLibraryTags(library); 17 processLibraryTags(handler, library);
18 handler.registerLibraryExports(library);
14 } 19 }
15 20
16 void scan(CompilationUnitElement compilationUnit) { 21 void scan(CompilationUnitElement compilationUnit) {
17 measure(() { 22 measure(() {
18 scanElements(compilationUnit); 23 scanElements(compilationUnit);
19 }); 24 });
20 } 25 }
21 26
22 void processLibraryTags(LibraryElement library) { 27 /**
28 * Processes the library tags in [library].
29 *
30 * The imported/exported libraries are loaded and processed recursively but
31 * the import/export scopes are not set up.
32 */
33 void processLibraryTags(ImportExportHandler handler, LibraryElement library) {
23 int tagState = TagState.NO_TAG_SEEN; 34 int tagState = TagState.NO_TAG_SEEN;
24 35
25 /** 36 /**
26 * If [value] is less than [tagState] complain and return 37 * If [value] is less than [tagState] complain and return
27 * [tagState]. Otherwise return the new value for [tagState] 38 * [tagState]. Otherwise return the new value for [tagState]
28 * (transition function for state machine). 39 * (transition function for state machine).
29 */ 40 */
30 int checkTag(int value, LibraryTag tag) { 41 int checkTag(int value, LibraryTag tag) {
31 if (tagState > value) { 42 if (tagState > value) {
32 compiler.reportError(tag, 'out of order'); 43 compiler.reportError(tag, 'out of order');
33 return tagState; 44 return tagState;
34 } 45 }
35 return TagState.NEXT[value]; 46 return TagState.NEXT[value];
36 } 47 }
37 48
38 LinkBuilder<Import> imports = new LinkBuilder<Import>(); 49 bool importsDartCore = false;
50 var importsExports = new LinkBuilder<ImportExport>();
Lasse Reichstein Nielsen 2012/09/28 07:45:36 ImportExport is very descriptive, but not very exp
Johnni Winther 2012/10/09 09:47:10 Done.
39 Uri base = library.entryCompilationUnit.script.uri; 51 Uri base = library.entryCompilationUnit.script.uri;
40 for (LibraryTag tag in library.tags.reverse()) { 52 for (LibraryTag tag in library.tags.reverse()) {
41 if (tag.isImport) { 53 if (tag.isImport) {
42 tagState = checkTag(TagState.IMPORT, tag); 54 tagState = checkTag(TagState.IMPORT, tag);
43 // It is not safe to import other libraries at this point as 55 // It is not safe to import other libraries at this point as
44 // another library could then observe the current library 56 // another library could then observe the current library
45 // before it fully declares all the members that are sourced 57 // before it fully declares all the members that are sourced
46 // in. 58 // in.
47 imports.addLast(tag); 59 if (tag.uri.dartString.slowToString() == 'dart:core') {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Using something called slowToString smells bad. Ho
Johnni Winther 2012/10/09 09:47:10 [uri] is a LiteralString, not a Uri.
60 importsDartCore = true;
61 }
62 importsExports.addLast(tag);
63 } else if (tag.isExport) {
64 tagState = checkTag(TagState.IMPORT, tag);
65 importsExports.addLast(tag);
48 } else if (tag.isLibraryName) { 66 } else if (tag.isLibraryName) {
49 tagState = checkTag(TagState.LIBRARY, tag); 67 tagState = checkTag(TagState.LIBRARY, tag);
50 if (library.libraryTag !== null) { 68 if (library.libraryTag !== null) {
51 compiler.cancel("duplicated library declaration", node: tag); 69 compiler.cancel("duplicated library declaration", node: tag);
52 } else { 70 } else {
53 library.libraryTag = tag; 71 library.libraryTag = tag;
54 } 72 }
55 } else if (tag.isPart) { 73 } else if (tag.isPart) {
56 StringNode uri = tag.uri; 74 StringNode uri = tag.uri;
57 Uri resolved = base.resolve(uri.dartString.slowToString()); 75 Uri resolved = base.resolve(uri.dartString.slowToString());
58 tagState = checkTag(TagState.SOURCE, tag); 76 tagState = checkTag(TagState.SOURCE, tag);
59 loadPart(tag, resolved, library); 77 loadPart(tag, resolved, library);
60 } else { 78 } else {
61 compiler.cancel("illegal script tag: ${tag.tag}", node: tag); 79 compiler.cancel("illegal script tag: ${tag}", node: tag);
62 } 80 }
63 } 81 }
64 82
65 // Apply patch, if any. 83 // Apply patch, if any.
66 if (library.uri.scheme == 'dart') { 84 if (library.uri.scheme == 'dart') {
67 compiler.patchDartLibrary(library, library.uri.path); 85 compiler.patchDartLibrary(handler, library, library.uri.path);
68 } 86 }
69 87
70 // Now that we have processed all the source tags, it is safe to 88 // Now that we have processed all the source tags, it is safe to
71 // start loading other libraries. 89 // start loading other libraries.
72 90
73 if (library.uri.scheme != 'dart' || library.uri.path != 'core') { 91 if (!importsDartCore ||
74 compiler.importCoreLibrary(library); 92 (library.uri.scheme != 'dart' || library.uri.path != 'core')) {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 I really can't read this. Please use if (!import
Johnni Winther 2012/10/09 09:47:10 Done.
93 handler.registerDependency(library, null,
94 compiler.importCoreLibrary(handler),
95 library.entryCompilationUnit);
75 } 96 }
76 97
77 for (Import tag in imports.toLink()) { 98 for (ImportExport tag in importsExports.toLink()) {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 We even have a class called ImportExport? Please c
Johnni Winther 2012/10/09 09:47:10 Done.
78 importLibraryFromTag(tag, library.entryCompilationUnit); 99 loadLibraryFromTag(handler, library, tag, library.entryCompilationUnit);
79 } 100 }
80 } 101 }
81 102
82 /** 103 /**
83 * Handle a part tag in the scope of [library]. The [path] given is used as 104 * Handle a part tag in the scope of [library]. The [path] given is used as
84 * is, any resolution should be done beforehand. 105 * is, any resolution should be done beforehand.
85 */ 106 */
86 void loadPart(Part part, Uri path, LibraryElement library) { 107 void loadPart(Part part, Uri path, LibraryElement library) {
87 Script sourceScript = compiler.readScript(path, part); 108 Script sourceScript = compiler.readScript(path, part);
88 CompilationUnitElement unit = 109 CompilationUnitElement unit =
89 new CompilationUnitElement(sourceScript, library); 110 new CompilationUnitElement(sourceScript, library);
90 compiler.withCurrentElement(unit, () => compiler.scanner.scan(unit)); 111 compiler.withCurrentElement(unit, () => compiler.scanner.scan(unit));
91 } 112 }
92 113
93 /** 114 /**
94 * Handle an import script tag by importing the referenced library into the 115 * Handle an import/export tag by loading the referenced library and
95 * current library. 116 * registering its dependency in [handler] for the computation of the import/
96 * Returns the resolved library [Uri]. 117 * export scope.
97 */ 118 */
98 Uri importLibraryFromTag(Import tag, 119 void loadLibraryFromTag(ImportExportHandler handler,
99 CompilationUnitElement compilationUnit) { 120 LibraryElement library,
121 ImportExport tag,
122 CompilationUnitElement compilationUnit) {
100 Uri base = compilationUnit.script.uri; 123 Uri base = compilationUnit.script.uri;
101 Uri resolved = base.resolve(tag.uri.dartString.slowToString()); 124 Uri resolved = base.resolve(tag.uri.dartString.slowToString());
102 LibraryElement importedLibrary = loadLibrary(resolved, tag.uri, resolved); 125 LibraryElement loadedLibrary =
103 importLibrary(compilationUnit.getLibrary(), 126 loadLibraryInternal(handler, resolved, tag.uri, resolved);
104 importedLibrary, 127 handler.registerDependency(library, tag, loadedLibrary, compilationUnit);
105 tag, 128
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Why are we passing both tag and compilationUnit? I
Johnni Winther 2012/10/09 09:47:10 CompilationUnit not needed anymore due to patch re
106 compilationUnit); 129 if (!loadedLibrary.hasLibraryName()) {
107 return resolved; 130 compiler.withCurrentElement(library, () {
131 compiler.reportError(tag === null ? null : tag.uri,
132 'no #library tag found in ${loadedLibrary.uri}');
133 });
134 }
108 } 135 }
109 136
110 void scanElements(CompilationUnitElement compilationUnit) { 137 void scanElements(CompilationUnitElement compilationUnit) {
111 Script script = compilationUnit.script; 138 Script script = compilationUnit.script;
112 Token tokens = new StringScanner(script.text).tokenize(); 139 Token tokens = new StringScanner(script.text).tokenize();
113 compiler.dietParser.dietParse(compilationUnit, tokens); 140 compiler.dietParser.dietParse(compilationUnit, tokens);
114 } 141 }
115 142
143 /**
144 * Loads the library located at [uri] and returns its [LibraryElement].
145 *
146 * If the library is not already loaded, the method creates the
147 * [LibraryElement] for the library and computes the import/export scope,
148 * loading and computing the import/export scopes of all required libraries in
149 * the process. The method handles cyclic dependency between libraries.
150 *
151 * This is the main entry point for [ScannerTask].
152 */
116 LibraryElement loadLibrary(Uri uri, Node node, Uri canonicalUri) { 153 LibraryElement loadLibrary(Uri uri, Node node, Uri canonicalUri) {
154 var handler = new ImportExportHandler(compiler);
155 LibraryElement library =
156 loadLibraryInternal(handler, uri, node, canonicalUri);
157 handler.computeExports();
158 return library;
159 }
160
161 LibraryElement loadLibraryInternal(ImportExportHandler handler,
162 Uri uri, Node node, Uri canonicalUri) {
117 bool newLibrary = false; 163 bool newLibrary = false;
118 LibraryElement library = 164 LibraryElement library =
119 compiler.libraries.putIfAbsent(uri.toString(), () { 165 compiler.libraries.putIfAbsent(uri.toString(), () {
120 newLibrary = true; 166 newLibrary = true;
121 Script script = compiler.readScript(uri, node); 167 Script script = compiler.readScript(uri, node);
122 LibraryElement element = new LibraryElement(script, canonicalUri); 168 LibraryElement element = new LibraryElement(script, canonicalUri);
169 handler.registerNewLibrary(element);
123 native.maybeEnableNative(compiler, element, uri); 170 native.maybeEnableNative(compiler, element, uri);
124 return element; 171 return element;
125 }); 172 });
126 if (newLibrary) { 173 if (newLibrary) {
127 compiler.withCurrentElement(library, () { 174 compiler.withCurrentElement(library, () {
128 scanLibrary(library); 175 scanLibrary(handler, library);
129 compiler.onLibraryLoaded(library, uri); 176 compiler.onLibraryLoaded(library, uri);
130 }); 177 });
131 } 178 }
132 return library; 179 return library;
133 } 180 }
134 181 }
135 void importLibrary(LibraryElement library, LibraryElement imported, 182
136 Import tag, [CompilationUnitElement compilationUnit]) { 183 class DietParserTask extends CompilerTask {
137 if (!imported.hasLibraryName()) { 184 DietParserTask(Compiler compiler) : super(compiler);
138 compiler.withCurrentElement(library, () { 185 final String name = 'Diet Parser';
139 compiler.reportError(tag === null ? null : tag.uri, 186
140 'no #library tag found in ${imported.uri}'); 187 dietParse(CompilationUnitElement compilationUnit, Token tokens) {
188 measure(() {
189 Function idGenerator = compiler.getNextFreeClassId;
190 ElementListener listener =
191 new ElementListener(compiler, compilationUnit, idGenerator);
192 PartialParser parser = new PartialParser(listener);
193 parser.parseUnit(tokens);
194 });
195 }
196 }
197
198 /**
199 * The fields of this class models a state machine for checking script
200 * tags come in the correct order.
201 */
202 class TagState {
203 static const int NO_TAG_SEEN = 0;
204 static const int LIBRARY = 1;
205 static const int IMPORT = 2;
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Includes export?
Johnni Winther 2012/10/09 09:47:10 Changed to IMPORT_OR_EXPORT.
206 static const int SOURCE = 3;
207 static const int RESOURCE = 4;
208
209 /** Next state. */
210 static const List<int> NEXT =
211 const <int>[NO_TAG_SEEN,
212 IMPORT, // Only one library tag is allowed.
213 IMPORT,
214 SOURCE,
215 RESOURCE];
216 }
217
218 /**
219 * Data class for handling import tags in [ImportExportHandler].
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Comment isn't helping me understand it. This is ju
220 */
221 class ImportData {
222 final Import tag;
223 final LibraryElement library;
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Add documentation for fields. What is this library
224 final CompilationUnitElement compilationUnit;
Lasse Reichstein Nielsen 2012/09/28 07:45:36 What is it a compilationUnit of? What is it used f
Johnni Winther 2012/10/09 09:47:10 Not needed anymore due to patch refactoring.
225
226 ImportData(this.tag, this.library, this.compilationUnit);
227 }
228
229 /**
230 * Data class used for the computation of import/export scopes by
231 * [ImportExportHandler].
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Also bad explanation. I'm not any wiser, and I que
232 */
233 class ImportExportData {
234 final LibraryElement library;
235 Link<ImportData> imports = const EmptyLink<ImportData>();
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Explain fields. Is this a work-list of import task
236 Map<Export, ImportExportData> dependencyMap =
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Just "dependencies". I can see it's a map, and if
237 new Map<Export, ImportExportData>();
Lasse Reichstein Nielsen 2012/09/28 07:45:36 This maps syntax to a data object. That seems odd.
238 Map<SourceString, Element> exportScope = new Map<SourceString, Element>();
Lasse Reichstein Nielsen 2012/09/28 07:45:36 This, I guess, is the export scope that is being b
239 Set<Element> pendingExportSet = new Set<Element>();
240
241 ImportExportData(LibraryElement this.library);
242 }
243
244 /**
245 * Helper class used for computing the possibly cyclic import/export scopes of
246 * a set of libraries.
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Are you sure this should not be a CompilerTask? It
247 *
248 * This class is used by [ScannerTask.loadLibrary] to collect all newly loaded
249 * libraries and to compute their import/export scopes through a fixed-point
250 * algorithm.
251 */
252 class ImportExportHandler {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Again: "ImportExport" is a bad name. (I'll stop no
253 final Compiler compiler;
254
255 Map<LibraryElement,ImportExportData> dataMap =
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Plase give this a better name that describes how i
256 new Map<LibraryElement,ImportExportData>();
257
258 ImportExportHandler(Compiler this.compiler);
259
260 /**
261 * Performs a fixed-point computation on the export scopes of all registered
262 * libraries and creates the import/export of the libraries based on the
263 * fixed-point.
264 */
265 void computeExports() {
266 bool changed = true;
267 while (changed) {
268 changed = false;
269 dataMap.forEach((LibraryElement library, ImportExportData data) {
270 var pendingExportSet = new Set<Element>.from(data.pendingExportSet);
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Why a Set? I'd think a list would have lower overh
Johnni Winther 2012/10/09 09:47:10 Done.
271 data.pendingExportSet.clear();
272 pendingExportSet.forEach((Element element) {
273 SourceString name = element.name;
274 Element existingElement =
275 data.exportScope.putIfAbsent(name, () => element);
276 if (existingElement !== null && existingElement !== element) {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 If you export the same library twice, should it be
277 element = data.exportScope[name] = new ErroneousElement(
278 MessageKind.DUPLICATE_EXPORT, [name], name, library);
279 }
280 data.dependencyMap.forEach((Export export,
281 ImportExportData exportData) {
282 // TODO(johnniwinther): Handle show and hide combinators.
283 if (exportData.exportScope[name] !== element) {
284 exportData.pendingExportSet.add(element);
285 changed = true;
286 }
287 });
288 });
141 }); 289 });
142 } 290 }
291
292 // Setup export scopes.
293 dataMap.forEach((LibraryElement library, ImportExportData data) {
294 data.library.exportScope = data.exportScope;
295 });
296
297 // Setup import scopes.
298 dataMap.forEach((LibraryElement library, ImportExportData data) {
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Join loops?
Johnni Winther 2012/10/09 09:47:10 Can't do. We need the completion of exports before
299 for (ImportData importData in data.imports) {
300 importLibrary(library, importData);
301 }
302 });
303 }
304
305 /**
306 * Registers that [importingLibrary] depends on [importedLibrary] through
307 * [tag].
308 */
309 void registerDependency(LibraryElement importingLibrary,
310 ImportExport tag,
311 LibraryElement importedLibrary,
312 CompilationUnitElement compilationUnit) {
313 if (tag is Export) {
314 dataMap[importedLibrary].dependencyMap[tag] = dataMap[importingLibrary];
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Because dataMap says nothing about what it does, t
315 } else {
316 ImportExportData data = dataMap[importingLibrary];
317 var importData = new ImportData(tag, importedLibrary, compilationUnit);
318 data.imports = data.imports.prepend(importData);
319 }
320 }
321
322 /**
323 * Registers [library] for the processing of its import/export scope.
324 */
325 void registerNewLibrary(LibraryElement library) {
326 dataMap[library] = new ImportExportData(library);
Lasse Reichstein Nielsen 2012/09/28 07:45:36 So the ImportExportData is the data associated wit
327 }
328
329 /**
330 * Registers all top-level entities of [library] as starting point for the
331 * fixed-point computation of the import/export scopes.
332 */
333 void registerLibraryExports(LibraryElement library) {
334 dataMap[library].pendingExportSet.addAll(
335 library.localScope.getValues().filter((Element element) {
336 return !element.name.isPrivate();
337 }));
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Ick. How about: ImportExportData libraryData = d
338 }
339
340 /**
341 * Imports the export scope of [import] to the import scope of [library].
342 */
343 void importLibrary(LibraryElement library, ImportData import) {
344 Import tag = import.tag;
345 LibraryElement imported = import.library;
143 if (tag !== null && tag.prefix !== null) { 346 if (tag !== null && tag.prefix !== null) {
144 SourceString prefix = tag.prefix.source; 347 SourceString prefix = tag.prefix.source;
145 Element e = library.find(prefix); 348 Element e = library.find(prefix);
146 if (e === null) { 349 if (e === null) {
350 CompilationUnitElement compilationUnit = import.compilationUnit;
147 if (compilationUnit === null) { 351 if (compilationUnit === null) {
148 compilationUnit = library.entryCompilationUnit; 352 compilationUnit = library.entryCompilationUnit;
149 } 353 }
150 e = new PrefixElement(prefix, compilationUnit, tag.getBeginToken()); 354 e = new PrefixElement(prefix, compilationUnit, tag.getBeginToken());
151 library.addToScope(e, compiler); 355 library.addToScope(e, compiler);
152 } 356 }
153 if (e.kind !== ElementKind.PREFIX) { 357 if (e.kind !== ElementKind.PREFIX) {
154 compiler.withCurrentElement(e, () { 358 compiler.withCurrentElement(e, () {
155 compiler.reportWarning(new Identifier(e.position()), 359 compiler.reportWarning(new Identifier(e.position()),
156 'duplicated definition'); 360 'duplicated definition');
157 }); 361 });
158 compiler.reportError(tag.prefix, 'duplicate defintion'); 362 compiler.reportError(tag.prefix, 'duplicate defintion');
Lasse Reichstein Nielsen 2012/09/28 07:45:36 Mmissing 'i" in "definition"
Johnni Winther 2012/10/09 09:47:10 Done.
159 } 363 }
160 PrefixElement prefixElement = e; 364 PrefixElement prefixElement = e;
161 imported.forEachExport((Element element) { 365 imported.forEachExport((Element element) {
366 // TODO(johnniwinther): Handle show and hide combinators.
162 Element existing = 367 Element existing =
163 prefixElement.imported.putIfAbsent(element.name, () => element); 368 prefixElement.imported.putIfAbsent(element.name, () => element);
164 if (existing !== element) { 369 if (existing !== element) {
165 compiler.withCurrentElement(existing, () { 370 compiler.withCurrentElement(existing, () {
166 compiler.reportWarning(new Identifier(existing.position()), 371 compiler.reportWarning(new Identifier(existing.position()),
167 'duplicated import'); 372 'duplicated import');
168 }); 373 });
169 compiler.withCurrentElement(element, () { 374 compiler.withCurrentElement(element, () {
170 compiler.reportError(new Identifier(element.position()), 375 compiler.reportError(new Identifier(element.position()),
171 'duplicated import'); 376 'duplicated import');
172 }); 377 });
173 } 378 }
174 }); 379 });
175 } else { 380 } else {
176 imported.forEachExport((Element element) { 381 imported.forEachExport((Element element) {
177 compiler.withCurrentElement(element, () { 382 compiler.withCurrentElement(element, () {
383 // TODO(johnniwinther): Handle show and hide combinators.
178 library.addImport(element, compiler); 384 library.addImport(element, compiler);
179 }); 385 });
180 }); 386 });
181 } 387 }
182 } 388 }
183 } 389 }
184
185 class DietParserTask extends CompilerTask {
186 DietParserTask(Compiler compiler) : super(compiler);
187 final String name = 'Diet Parser';
188
189 dietParse(CompilationUnitElement compilationUnit, Token tokens) {
190 measure(() {
191 Function idGenerator = compiler.getNextFreeClassId;
192 ElementListener listener =
193 new ElementListener(compiler, compilationUnit, idGenerator);
194 PartialParser parser = new PartialParser(listener);
195 parser.parseUnit(tokens);
196 });
197 }
198 }
199
200 /**
201 * The fields of this class models a state machine for checking script
202 * tags come in the correct order.
203 */
204 class TagState {
205 static const int NO_TAG_SEEN = 0;
206 static const int LIBRARY = 1;
207 static const int IMPORT = 2;
208 static const int SOURCE = 3;
209 static const int RESOURCE = 4;
210
211 /** Next state. */
212 static const List<int> NEXT =
213 const <int>[NO_TAG_SEEN,
214 IMPORT, // Only one library tag is allowed.
215 IMPORT,
216 SOURCE,
217 RESOURCE];
218 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698