Index: pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart |
diff --git a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart |
index c1122a4a8eff4bff503c0214a19dcc9f4f1ce873..c1174f5f1c6bb7af7cfe178dc52dba6fb3645772 100644 |
--- a/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart |
+++ b/pkg/front_end/lib/src/fasta/analyzer/ast_builder.dart |
@@ -379,7 +379,7 @@ class AstBuilder extends ScopeListener { |
debugEvent("VariablesDeclaration"); |
List<VariableDeclaration> variables = popList(count); |
TypeName type = pop(); |
- pop(); // Modifiers. |
+ pop(); // TODO(paulberry): Modifiers. |
push(ast.variableDeclarationStatement( |
ast.variableDeclarationList(null, null, null, type, variables), |
toAnalyzerToken(endToken))); |
@@ -570,7 +570,8 @@ class AstBuilder extends ScopeListener { |
} else { |
name = nameOrFunctionTypedParameter; |
TypeName type = pop(); |
- Token keyword = _popOptionalSingleModifier(); |
+ _Modifiers modifiers = pop(); |
+ Token keyword = modifiers?.finalConstOrVarKeyword; |
pop(); // TODO(paulberry): Metadata. |
if (thisKeyword == null) { |
node = ast.simpleFormalParameter2( |
@@ -613,8 +614,8 @@ class AstBuilder extends ScopeListener { |
TypeName returnType = pop(); |
{ |
- List<Token> modifiers = pop(); |
- if (modifiers.isNotEmpty) { |
+ _Modifiers modifiers = pop(); |
+ if (modifiers != null) { |
// TODO(scheglov): Report error. |
internalError('Unexpected modifier. Report an error.'); |
} |
@@ -763,7 +764,11 @@ class AstBuilder extends ScopeListener { |
void handleModifiers(int count) { |
debugEvent("Modifiers"); |
- push(popList(count) ?? const <Token>[]); |
+ if (count == 0) { |
+ push(NullValue.Modifiers); |
+ } else { |
+ push(new _Modifiers(popList(count))); |
+ } |
} |
FunctionBody _endFunctionBody() { |
@@ -796,7 +801,8 @@ class AstBuilder extends ScopeListener { |
SimpleIdentifier name = pop(); |
analyzer.Token propertyKeyword = toAnalyzerToken(getOrSet); |
TypeAnnotation returnType = pop(); |
- Token externalKeyword = _popOptionalSingleModifier(); |
+ _Modifiers modifiers = pop(); |
+ Token externalKeyword = modifiers?.externalKeyword; |
List<Annotation> metadata = pop(); |
// TODO(paulberry): capture doc comments. See dartbug.com/28851. |
Comment comment = null; |
@@ -983,7 +989,8 @@ class AstBuilder extends ScopeListener { |
SimpleIdentifier name = pop(); |
assert(className == name.name); |
className = null; |
- Token abstractKeyword = _popOptionalSingleModifier(); |
+ _Modifiers modifiers = pop(); |
+ Token abstractKeyword = modifiers?.abstractKeyword; |
List<Annotation> metadata = pop(); |
// TODO(paulberry): capture doc comments. See dartbug.com/28851. |
Comment comment = null; |
@@ -1031,7 +1038,8 @@ class AstBuilder extends ScopeListener { |
analyzer.Token equals = toAnalyzerToken(equalsToken); |
TypeParameterList typeParameters = pop(); |
SimpleIdentifier name = pop(); |
- Token abstractKeyword = _popOptionalSingleModifier(); |
+ _Modifiers modifiers = pop(); |
+ Token abstractKeyword = modifiers?.abstractKeyword; |
List<Annotation> metadata = pop(); |
// TODO(paulberry): capture doc comments. See dartbug.com/28851. |
Comment comment = null; |
@@ -1137,7 +1145,8 @@ class AstBuilder extends ScopeListener { |
debugEvent("TopLevelFields"); |
List<VariableDeclaration> variables = popList(count); |
TypeAnnotation type = pop(); |
- Token keyword = _popOptionalSingleModifier(); |
+ _Modifiers modifiers = pop(); |
+ Token keyword = modifiers?.finalConstOrVarKeyword; |
var variableList = ast.variableDeclarationList( |
null, null, toAnalyzerToken(keyword), type, variables); |
List<Annotation> metadata = pop(); |
@@ -1182,28 +1191,7 @@ class AstBuilder extends ScopeListener { |
TypeParameterList typeParameters = pop(); // TODO(paulberry) |
var name = pop(); |
TypeAnnotation returnType = pop(); // TODO(paulberry) |
- Token modifierKeyword = null; // TODO(paulberry) |
- Token externalKeyword = null; |
- Token constKeyword = null; |
- Token factoryKeyword = null; |
- List<Token> modifiers = pop(); |
- for (Token modifier in modifiers) { |
- String value = modifier.stringValue; |
- if (identical('external', value)) { |
- // TODO(scheglov): Check the order and uniqueness. |
- externalKeyword = modifier; |
- } else if (identical('const', value)) { |
- // TODO(scheglov): Check the order and uniqueness. |
- constKeyword = modifier; |
- } else if (identical('factory', value)) { |
- // TODO(scheglov): Check the order and uniqueness. |
- factoryKeyword = modifier; |
- } else { |
- // TODO(scheglov): Report error. |
- internalError("Invalid modifier ($value). Report an error."); |
- } |
- } |
- |
+ _Modifiers modifiers = pop(); |
List<Annotation> metadata = pop(); |
// TODO(paulberry): capture doc comments. See dartbug.com/28851. |
Comment comment = null; |
@@ -1213,9 +1201,9 @@ class AstBuilder extends ScopeListener { |
push(ast.constructorDeclaration( |
comment, |
metadata, |
- toAnalyzerToken(externalKeyword), |
- toAnalyzerToken(constKeyword), |
- toAnalyzerToken(factoryKeyword), |
+ toAnalyzerToken(modifiers?.externalKeyword), |
+ toAnalyzerToken(modifiers?.finalConstOrVarKeyword), |
+ null, // TODO(paulberry): factoryKeyword |
returnType, |
toAnalyzerToken(period), |
name, |
@@ -1230,8 +1218,9 @@ class AstBuilder extends ScopeListener { |
push(ast.methodDeclaration( |
comment, |
metadata, |
- toAnalyzerToken(externalKeyword), |
- toAnalyzerToken(modifierKeyword), |
+ toAnalyzerToken(modifiers?.externalKeyword), |
+ toAnalyzerToken( |
+ modifiers?.abstractKeyword ?? modifiers?.staticKeyword), |
returnType, |
toAnalyzerToken(getOrSet), |
toAnalyzerToken(operatorKeyword), |
@@ -1351,24 +1340,9 @@ class AstBuilder extends ScopeListener { |
debugEvent("Fields"); |
List<VariableDeclaration> variables = popList(count); |
TypeAnnotation type = pop(); |
- List<Token> modifiers = pop(); |
- Token staticKeyword; |
- Token keyword; |
- for (Token modifier in modifiers) { |
- String value = modifier.stringValue; |
- if (identical('static', value)) { |
- // TODO(paulberry): Check the order and uniqueness. |
- staticKeyword = modifier; |
- } else if (identical('var', value)) { |
- // TODO(paulberry): Check the order and uniqueness. |
- keyword = modifier; |
- } else { |
- // TODO(paulberry): Report error. |
- internalError("Invalid modifier ($value). Report an error."); |
- } |
- } |
- var variableList = ast.variableDeclarationList( |
- null, null, toAnalyzerToken(keyword), type, variables); |
+ _Modifiers modifiers = pop(); |
+ var variableList = ast.variableDeclarationList(null, null, |
+ toAnalyzerToken(modifiers?.finalConstOrVarKeyword), type, variables); |
List<Annotation> metadata = pop(); |
// TODO(paulberry): capture doc comments. See dartbug.com/28851. |
Comment comment = null; |
@@ -1376,7 +1350,7 @@ class AstBuilder extends ScopeListener { |
comment: comment, |
metadata: metadata, |
covariantKeyword: toAnalyzerToken(covariantKeyword), |
- staticKeyword: toAnalyzerToken(staticKeyword), |
+ staticKeyword: toAnalyzerToken(modifiers?.staticKeyword), |
fieldList: variableList, |
semicolon: toAnalyzerToken(endToken))); |
} |
@@ -1388,24 +1362,6 @@ class AstBuilder extends ScopeListener { |
ast.simpleIdentifier(toAnalyzerToken(token), isDeclaration: true))); |
} |
- /** |
- * Pop the modifiers list, if the list is empty return `null`, if the list |
- * has one item return it; otherwise return `null`. |
- */ |
- Token _popOptionalSingleModifier() { |
- List<Token> modifiers = pop(); |
- if (modifiers.length == 0) { |
- return null; |
- } else if (modifiers.length == 1) { |
- // TODO(scheglov): Verify that the modifier is valid. |
- return modifiers[0]; |
- } else { |
- // TODO(scheglov): Report error. |
- internalError("Invalid modifier. Report an error."); |
- return null; |
- } |
- } |
- |
ParameterKind _toAnalyzerParameterKind(FormalParameterType type) { |
if (type == FormalParameterType.POSITIONAL) { |
return ParameterKind.POSITIONAL; |
@@ -1475,3 +1431,36 @@ class _OperatorName { |
_OperatorName(this.operatorKeyword, this.name); |
} |
+ |
+/// Data structure placed on the stack to represent a non-empty sequence |
+/// of modifiers. |
+class _Modifiers { |
+ Token abstractKeyword; |
+ Token externalKeyword; |
+ Token finalConstOrVarKeyword; |
+ Token staticKeyword; |
+ |
+ _Modifiers(List<Token> modifierTokens) { |
+ // No need to check the order and uniqueness of the modifiers, or that |
+ // disallowed modifiers are not used; the parser should do that. |
+ // TODO(paulberry,ahe): implement the necessary logic in the parser. |
+ for (var token in modifierTokens) { |
+ var s = token.value; |
+ if (identical('abstract', s)) { |
+ abstractKeyword = token; |
+ } else if (identical('const', s)) { |
+ finalConstOrVarKeyword = token; |
+ } else if (identical('external', s)) { |
+ externalKeyword = token; |
+ } else if (identical('final', s)) { |
+ finalConstOrVarKeyword = token; |
+ } else if (identical('static', s)) { |
+ staticKeyword = token; |
+ } else if (identical('var', s)) { |
+ finalConstOrVarKeyword = token; |
+ } else { |
+ internalError('Unhandled modifier: $s'); |
+ } |
+ } |
+ } |
+} |