Index: dart/compiler/java/com/google/dart/compiler/parser/AbstractParser.java |
diff --git a/dart/compiler/java/com/google/dart/compiler/parser/AbstractParser.java b/dart/compiler/java/com/google/dart/compiler/parser/AbstractParser.java |
deleted file mode 100644 |
index 6295eb197414d58d1c6b0bf09b65dd69c5b81da9..0000000000000000000000000000000000000000 |
--- a/dart/compiler/java/com/google/dart/compiler/parser/AbstractParser.java |
+++ /dev/null |
@@ -1,257 +0,0 @@ |
-// Copyright (c) 2012, 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. |
- |
-package com.google.dart.compiler.parser; |
- |
-import com.google.common.collect.Lists; |
-import com.google.common.collect.Maps; |
-import com.google.common.collect.Sets; |
-import com.google.dart.compiler.DartCompilationError; |
-import com.google.dart.compiler.ErrorCode; |
-import com.google.dart.compiler.parser.DartScanner.Location; |
- |
-import java.util.List; |
-import java.util.Map; |
-import java.util.Set; |
- |
-/** |
- * Abstract base class for sharing common utility methods between implementation |
- * classes, like {@link DartParser}. |
- */ |
-abstract class AbstractParser { |
- |
- private final TerminalAnnotationsCache terminalAnnotationsCache = new TerminalAnnotationsCache(); |
- protected final ParserContext ctx; |
- private int lastErrorPosition = Integer.MIN_VALUE; |
- |
- protected AbstractParser(ParserContext ctx) { |
- this.ctx = ctx; |
- } |
- |
- protected boolean EOS() { |
- return match(Token.EOS) || match(Token.ILLEGAL); |
- } |
- |
- private static class TerminalAnnotationsCache { |
- private Map<String, Class<?>> classes; |
- private Map<String, List<Token>> methods; |
- |
- private void init(StackTraceElement[] stackTrace) { |
- // This method, she is slow. |
- if (classes == null) { |
- classes = Maps.newHashMap(); |
- methods = Maps.newHashMap(); |
- } |
- |
- for (StackTraceElement frame : stackTrace) { |
- Class<?> thisClass = classes.get(frame.getClassName()); |
- if (thisClass == null) { |
- try { |
- thisClass = Class.forName(frame.getClassName()); |
- |
- for (java.lang.reflect.Method method : thisClass |
- .getDeclaredMethods()) { |
- List<Token> tokens = methods.get(method.getName()); |
- if (tokens == null) { |
- tokens = Lists.newArrayList(); |
- methods.put(thisClass.getName() + "." + method.getName(), tokens); |
- } |
- // look for annotations |
- Terminals terminalsAnnotation = method |
- .getAnnotation(Terminals.class); |
- if (terminalsAnnotation != null) { |
- for (Token token : terminalsAnnotation.tokens()) { |
- tokens.add(token); |
- } |
- } |
- } |
- } catch (ClassNotFoundException e) { |
- // ignored |
- } |
- classes.put(frame.getClassName(), null); |
- } |
- } |
- } |
- |
- public Set<Token> terminalsForStack(StackTraceElement[] stackTrace) { |
- Set<Token> results = Sets.newHashSet(); |
- for (StackTraceElement frame: stackTrace) { |
- List<Token> found = methods.get(frame.getClassName() + "." + frame.getMethodName()); |
- if (found != null) { |
- results.addAll(found); |
- } |
- } |
- return results; |
- } |
- } |
- |
- /** |
- * Uses reflection to walk up the stack and look for @Terminals method |
- * annotations. It gathers up the tokens in these annotations and returns them |
- * to the caller. This is intended for use in parser recovery, so that we |
- * don't accidentally consume a token that could be used to complete a |
- * non-terminal higher up in the stack. |
- */ |
- protected Set<Token> collectTerminalAnnotations() { |
- StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); |
- // Get methods for every class and associated Terminals annotations & stick them in a hash |
- terminalAnnotationsCache.init(stackTrace); |
- // Create the set of terminals to return |
- return terminalAnnotationsCache.terminalsForStack(stackTrace); |
- } |
- |
- /** |
- * If the expectedToken is encountered it is consumed and <code>true</code> is returned. |
- * If the expectedToken is not found, an error is reported. |
- * The token will only be consumed if it is not among the set of tokens that can be handled |
- * by a method currently on the stack. See the {@link Terminals annotation} |
- * |
- * @param expectedToken The token to expect next in the stream. |
- */ |
- protected boolean expect(Token expectedToken) { |
- if (!optional(expectedToken)) { |
- |
- /* |
- * Save the current token, then advance to make sure that we have the |
- * right position. |
- */ |
- Token actualToken = peek(0); |
- |
- Set<Token> possibleTerminals = collectTerminalAnnotations(); |
- |
- ctx.begin(); |
- ctx.advance(); |
- reportUnexpectedToken(position(), expectedToken, actualToken); |
- // Don't consume tokens someone else could use to cleanly terminate the |
- // statement. |
- if (possibleTerminals.contains(actualToken)) { |
- ctx.rollback(); |
- return false; |
- } |
- ctx.done(null); |
- |
- // Recover from the middle of string interpolation |
- if (actualToken.equals(Token.STRING_EMBED_EXP_START) |
- || actualToken.equals(Token.STRING_EMBED_EXP_END)) { |
- while (!EOS()) { |
- Token nextToken = next(); |
- if (nextToken.equals(Token.STRING_LAST_SEGMENT)) { |
- break; |
- } |
- next(); |
- } |
- } |
- return false; |
- } |
- return true; |
- } |
- |
- protected Location peekTokenLocation(int n) { |
- assert (n >= 0); |
- return ctx.peekTokenLocation(n); |
- } |
- |
- protected String getPeekTokenValue(int n) { |
- assert (n >= 0); |
- String value = ctx.peekTokenString(n); |
- return value; |
- } |
- |
- protected boolean match(Token token) { |
- return peek(0) == token; |
- } |
- |
- protected Token next() { |
- ctx.advance(); |
- return ctx.getCurrentToken(); |
- } |
- |
- protected boolean optionalPseudoKeyword(String keyword) { |
- if (!peekPseudoKeyword(0, keyword)) { |
- return false; |
- } |
- next(); |
- return true; |
- } |
- |
- protected boolean optional(Token token) { |
- if (peek(0) != token) { |
- return false; |
- } |
- next(); |
- return true; |
- } |
- |
- protected Token peek(int n) { |
- return ctx.peek(n); |
- } |
- |
- protected boolean peekPseudoKeyword(int n, String keyword) { |
- return (peek(n) == Token.IDENTIFIER) |
- && keyword.equals(getPeekTokenValue(n)); |
- } |
- |
- protected int position() { |
- DartScanner.Location tokenLocation = ctx.getTokenLocation(); |
- return tokenLocation != null ? tokenLocation.getBegin() : 0; |
- } |
- |
- /** |
- * Report a syntax error, unless an error has already been reported at the |
- * given or a later position. |
- */ |
- protected void reportError(int position, |
- ErrorCode errorCode, Object... arguments) { |
- DartScanner.Location location = ctx.getTokenLocation(); |
- if (location.getBegin() <= lastErrorPosition) { |
- return; |
- } |
- DartCompilationError dartError = new DartCompilationError(ctx.getSource(), |
- location, errorCode, arguments); |
- lastErrorPosition = position; |
- ctx.error(dartError); |
- } |
- |
- /** |
- * Even though you pass a 'Position' to {@link #reportError} above, it only |
- * uses that to prevent logging more than one error at that position. This |
- * method actually uses the passed position to create the error event. |
- */ |
- protected void reportErrorAtPosition(int startPosition, |
- int endPosition, |
- ErrorCode errorCode, Object... arguments) { |
- DartScanner.Location location = ctx.getTokenLocation(); |
- if (location.getBegin() <= lastErrorPosition) { |
- return; |
- } |
- DartCompilationError dartError = new DartCompilationError(ctx.getSource(), |
- new Location(startPosition, endPosition), errorCode, arguments); |
- ctx.error(dartError); |
- } |
- |
- protected void reportUnexpectedToken(int position, |
- Token expected, Token actual) { |
- if (expected == Token.EOS) { |
- reportError(position, ParserErrorCode.EXPECTED_EOS, actual); |
- } else if (expected == Token.IDENTIFIER) { |
- reportError(position, ParserErrorCode.INVALID_IDENTIFIER, actual); |
- } else if (expected == null) { |
- reportError(position, ParserErrorCode.UNEXPECTED_TOKEN, actual); |
- } else { |
- reportError(position, ParserErrorCode.EXPECTED_TOKEN, actual, expected); |
- } |
- } |
- |
- protected void setPeek(int n, Token token) { |
- assert n == 0; // so far, n is always zero |
- ctx.replaceNextToken(token); |
- } |
- |
- protected boolean consume(Token token) { |
- boolean result = (peek(0) == token); |
- assert (result); |
- next(); |
- return result; |
- } |
-} |