Chromium Code Reviews| Index: dart/frog/leg/scanner/parser.dart |
| diff --git a/dart/frog/leg/scanner/parser.dart b/dart/frog/leg/scanner/parser.dart |
| index 77f853a49926e44e39b771749b34b19f849ca28c..d3a1abb65d5c216cf07172db306e70d6af378f92 100644 |
| --- a/dart/frog/leg/scanner/parser.dart |
| +++ b/dart/frog/leg/scanner/parser.dart |
| @@ -6,10 +6,29 @@ |
| * An event generating parser of Dart programs. This parser expects |
| * all tokens in a linked list. |
| */ |
| -class Parser<L extends Listener> { |
| +class PartialParser<L extends Listener> { |
| final L listener; |
| + Function beginTypeArguments; |
|
kasperl
2011/11/10 06:37:34
I think these function fields deserve a comment. W
ahe
2011/11/10 07:59:46
I'll wrap these in a class and clean it up. After
|
| + Function parseTypeFunction; |
| + Function endTypeArguments; |
| + Function handleNoTypeArguments; |
| - Parser(L this.listener); |
| + Function beginTypeVariables; |
| + Function parseTypeVariableFunction; |
| + Function endTypeVariables; |
| + Function handleNoTypeVariables; |
| + |
| + PartialParser(L this.listener) { |
| + beginTypeArguments = listener.beginTypeArguments; |
| + parseTypeFunction = parseType; |
| + endTypeArguments = listener.endTypeArguments; |
| + handleNoTypeArguments = listener.handleNoTypeArguments; |
| + |
| + beginTypeVariables = listener.beginTypeVariables; |
| + parseTypeVariableFunction = parseTypeVariable; |
| + endTypeVariables = listener.endTypeVariables; |
| + handleNoTypeVariables = listener.handleNoTypeVariables; |
| + } |
| // TODO(ahe): Rename this method. It is too subtle compared to token.next. |
| Token next(Token token) => checkEof(token.next); |
| @@ -169,11 +188,26 @@ class Parser<L extends Listener> { |
| listener.beginClass(token); |
| token = parseIdentifier(next(token)); |
| token = parseTypeVariablesOpt(token); |
| - token = parseSuperclassClauseOpt(token); |
| - token = parseImplementsOpt(token); |
| + Token extendsKeyword; |
| + if (optional('extends', token)) { |
| + extendsKeyword = token; |
| + token = parseType(next(token)); |
| + } else { |
| + extendsKeyword = null; |
| + listener.handleNoType(token); |
|
ngeoffray
2011/11/10 08:27:42
Should that be handleNoSuperType instead?
ahe
2011/11/10 13:37:23
Not necessarily. I could change it if someone has
|
| + } |
| + Token implementsKeyword; |
| + int interfacesCount = 0; |
| + if (optional('implements', token)) { |
| + do { |
| + token = parseType(next(token)); |
| + ++interfacesCount; |
| + } while (optional(',', token)); |
| + } |
| token = parseNativeClassClauseOpt(token); |
| token = parseClassBody(token); |
| - listener.endClass(begin, token); |
| + listener.endClass(interfacesCount, begin, extendsKeyword, implementsKeyword, |
| + token); |
| return token.next; |
| } |
| @@ -201,24 +235,6 @@ class Parser<L extends Listener> { |
| return next(token); |
| } |
| - Token parseTypeVariablesOpt(Token token) { |
| - if (!optional('<', token)) { |
| - listener.handleNoTypeVariables(token); |
| - return token; |
| - } |
| - return parseTypeVariables(token); |
| - } |
| - |
| - Token parseTypeVariables(Token token) { |
| - expect('<', token); |
| - listener.beginTypeVariables(token); |
| - do { |
| - token = parseTypeVariable(next(token)); |
| - } while (optional(',', token)); |
| - listener.endTypeVariables(token); |
| - return expect('>', token); |
| - } |
| - |
| Token expect(String string, Token token) { |
| if (string !== token.stringValue) { |
| return listener.expected(string, token); |
| @@ -229,20 +245,17 @@ class Parser<L extends Listener> { |
| Token parseTypeVariable(Token token) { |
| listener.beginTypeVariable(token); |
| token = parseIdentifier(token); |
| - token = parseSuperclassClauseOpt(token); |
| + if (optional('extends', token)) { |
| + token = parseType(next(token)); |
| + } else { |
| + listener.handleNoType(token); |
| + } |
| listener.endTypeVariable(token); |
| return token; |
| } |
| bool optional(String value, Token token) => value === token.stringValue; |
| - Token parseSuperclassClauseOpt(Token token) { |
| - if (optional('extends', token)) { |
| - return parseType(next(token)); |
| - } |
| - return token; |
| - } |
| - |
| Token parseType(Token token) { |
| // TODO(ahe): Rename this method to parseTypeOrVar? |
| if (isIdentifier(token)) { |
| @@ -264,22 +277,29 @@ class Parser<L extends Listener> { |
| } |
| Token parseTypeArgumentsOpt(Token token) { |
| - if (optional('<', token)) { |
| - listener.beginTypeArguments(next(token)); |
| - do { |
| - token = parseType(next(token)); |
| - } while (optional(',', token)); |
| - return expect('>', token); |
| - } |
| - return token; |
| + return parseStuff(token, beginTypeArguments, parseTypeFunction, |
| + endTypeArguments, handleNoTypeArguments); |
| } |
| - Token parseImplementsOpt(Token token) { |
| - if (optional('implements', token)) { |
| + Token parseTypeVariablesOpt(Token token) { |
| + return parseStuff(token, beginTypeVariables, parseTypeVariableFunction, |
| + endTypeVariables, handleNoTypeVariables); |
| + } |
| + |
| + Token parseStuff(Token token, Function beginStuff, Function stuffParser, |
|
kasperl
2011/11/10 06:37:34
It would be nice with a more saying name for this.
ahe
2011/11/10 13:37:23
Added TODO.
|
| + Function endStuff, Function handleNoStuff) { |
| + if (optional('<', token)) { |
| + Token begin = token; |
| + beginStuff(begin); |
| + int count = 0; |
| do { |
| - token = parseType(next(token)); |
| + token = stuffParser(next(token)); |
| + ++count; |
| } while (optional(',', token)); |
| + endStuff(count, begin, token); |
| + return expect('>', token); |
| } |
| + handleNoStuff(token); |
| return token; |
| } |
| @@ -348,8 +368,8 @@ class Parser<L extends Listener> { |
| } |
| } |
| -class BodyParser extends Parser/* <BodyListener> Frog bug #320 */ { |
| - BodyParser(BodyListener listener) : super(listener); |
| +class Parser extends PartialParser/* <NodeListener> Frog bug #320 */ { |
| + Parser(NodeListener listener) : super(listener); |
| Token parseFunction(Token token) { |
| listener.beginFunction(token); |