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

Side by Side Diff: compiler/java/com/google/dart/compiler/parser/AbstractParser.java

Issue 10005040: Using annotations to help with parser recovery (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed unrelated file Created 8 years, 8 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
« no previous file with comments | « no previous file | compiler/java/com/google/dart/compiler/parser/DartParser.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, 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 package com.google.dart.compiler.parser; 5 package com.google.dart.compiler.parser;
6 6
7 import com.google.common.collect.Lists;
8 import com.google.common.collect.Maps;
9 import com.google.common.collect.Sets;
7 import com.google.dart.compiler.DartCompilationError; 10 import com.google.dart.compiler.DartCompilationError;
8 import com.google.dart.compiler.ErrorCode; 11 import com.google.dart.compiler.ErrorCode;
9 import com.google.dart.compiler.parser.DartScanner.Location; 12 import com.google.dart.compiler.parser.DartScanner.Location;
10 13
14 import java.lang.annotation.Annotation;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
11 /** 19 /**
12 * Abstract base class for sharing common utility methods between implementation 20 * Abstract base class for sharing common utility methods between implementation
13 * classes, like {@link DartParser}. 21 * classes, like {@link DartParser}.
14 */ 22 */
15 abstract class AbstractParser { 23 abstract class AbstractParser {
16 24
17 protected final ParserContext ctx; 25 protected final ParserContext ctx;
18 private int lastErrorPosition = Integer.MIN_VALUE; 26 private int lastErrorPosition = Integer.MIN_VALUE;
19 27
20 protected AbstractParser(ParserContext ctx) { 28 protected AbstractParser(ParserContext ctx) {
21 this.ctx = ctx; 29 this.ctx = ctx;
22 } 30 }
23 31
24 protected boolean EOS() { 32 protected boolean EOS() {
25 return match(Token.EOS) || match(Token.ILLEGAL); 33 return match(Token.EOS) || match(Token.ILLEGAL);
26 } 34 }
27 35
36 private static class TerminalAnnotationsCache {
37 private static Map<String, Class<?>> classes;
38 private static Map<String, List<Token>> methods;
39
40 private static void init(StackTraceElement[] stackTrace) {
41 if (classes == null) {
42 classes = Maps.newHashMap();
43 methods = Maps.newHashMap();
44 }
45
46 for (StackTraceElement frame : stackTrace) {
47 Class<?> thisClass = classes.get(frame.getClassName());
48 if (thisClass == null) {
49 try {
50 thisClass = Class.forName(frame.getClassName());
51
52 for (java.lang.reflect.Method method : thisClass
53 .getDeclaredMethods()) {
54 List<Token> tokens = methods.get(method.getName());
55 if (tokens == null) {
56 tokens = Lists.newArrayList();
57 methods.put(thisClass.getName() + "." + method.getName(), tokens );
58 }
59 // look for annotations
60 Terminals terminalsAnnotation = (Terminals) method
61 .getAnnotation(Terminals.class);
62 if (terminalsAnnotation != null) {
63 for (Token token : terminalsAnnotation.tokens()) {
64 tokens.add(token);
65 }
66 }
67 }
68 } catch (ClassNotFoundException e) {
69 // ignored
70 }
71 classes.put(frame.getClassName(), null);
72 }
73 }
74 }
75
76 public static Set<Token> terminalsForStack(StackTraceElement[] stackTrace) {
77 Set<Token> results = Sets.newHashSet();
78 for (StackTraceElement frame: stackTrace) {
79 List<Token> found = methods.get(frame.getClassName() + "." + frame.getMe thodName());
80 if (found != null) {
81 results.addAll(found);
82 }
83 }
84 return results;
85 }
86 }
87
88
89 /**
90 * Uses reflection to walk up the stack and look for @Terminals method
91 * annotations. It gathers up the tokens in these annotations and returns them
92 * to the caller. This is intended for use in parser recovery, so that we
93 * don't accidentally consume a token that could be used to complete a
94 * non-terminal higher up in the stack.
95 */
96 protected Set<Token> collectTerminalAnnotations() {
97 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
98 // Get methods for every class and associated Terminals annotations & stick them in a hash
99 TerminalAnnotationsCache.init(stackTrace);
100 // Create the set of terminals to return
101 return TerminalAnnotationsCache.terminalsForStack(stackTrace);
102 }
103
28 protected boolean expect(Token expectedToken) { 104 protected boolean expect(Token expectedToken) {
29 if (!optional(expectedToken)) { 105 if (!optional(expectedToken)) {
106
30 /* 107 /*
31 * Save the current token, then advance to make sure that we have the 108 * Save the current token, then advance to make sure that we have the
32 * right position. 109 * right position.
33 */ 110 */
34 Token actualToken = peek(0); 111 Token actualToken = peek(0);
112
113 Set<Token> possibleTerminals = collectTerminalAnnotations();
114
115 ctx.begin();
35 ctx.advance(); 116 ctx.advance();
36 reportUnexpectedToken(position(), expectedToken, actualToken); 117 reportUnexpectedToken(position(), expectedToken, actualToken);
118 // Don't consume tokens someone else could use to cleanly terminate the
119 // statement.
120 if (possibleTerminals.contains(actualToken)) {
121 ctx.rollback();
122 return false;
123 }
124 ctx.done(null);
125
37 // Recover from the middle of string interpolation 126 // Recover from the middle of string interpolation
38 if (actualToken.equals(Token.STRING_EMBED_EXP_START) || 127 if (actualToken.equals(Token.STRING_EMBED_EXP_START)
39 actualToken.equals(Token.STRING_EMBED_EXP_END)) { 128 || actualToken.equals(Token.STRING_EMBED_EXP_END)) {
40 while(!EOS()) { 129 while (!EOS()) {
41 Token nextToken = next(); 130 Token nextToken = next();
42 if (nextToken.equals(Token.STRING_LAST_SEGMENT)) { 131 if (nextToken.equals(Token.STRING_LAST_SEGMENT)) {
43 break; 132 break;
44 } 133 }
45 next(); 134 next();
46 } 135 }
47 } 136 }
137
48 return false; 138 return false;
49 } 139 }
50 return true; 140 return true;
51 } 141 }
52 142
53 protected String getPeekTokenValue(int n) { 143 protected String getPeekTokenValue(int n) {
54 assert (n >= 0); 144 assert (n >= 0);
55 String value = ctx.peekTokenString(n); 145 String value = ctx.peekTokenString(n);
56 return value; 146 return value;
57 } 147 }
(...skipping 21 matching lines...) Expand all
79 } 169 }
80 next(); 170 next();
81 return true; 171 return true;
82 } 172 }
83 173
84 protected Token peek(int n) { 174 protected Token peek(int n) {
85 return ctx.peek(n); 175 return ctx.peek(n);
86 } 176 }
87 177
88 protected boolean peekPseudoKeyword(int n, String keyword) { 178 protected boolean peekPseudoKeyword(int n, String keyword) {
89 return (peek(n) == Token.IDENTIFIER) && keyword.equals(getPeekTokenValue(n)) ; 179 return (peek(n) == Token.IDENTIFIER)
180 && keyword.equals(getPeekTokenValue(n));
90 } 181 }
91 182
92 protected DartScanner.Position position() { 183 protected DartScanner.Position position() {
93 DartScanner.Location tokenLocation = ctx.getTokenLocation(); 184 DartScanner.Location tokenLocation = ctx.getTokenLocation();
94 return tokenLocation != null ? tokenLocation.getBegin() : new DartScanner.Po sition(0, 1, 1); 185 return tokenLocation != null ? tokenLocation.getBegin()
186 : new DartScanner.Position(0, 1, 1);
95 } 187 }
96 188
97 /** 189 /**
98 * Report a syntax error, unless an error has already been reported at the giv en or a later 190 * Report a syntax error, unless an error has already been reported at the
99 * position. 191 * given or a later position.
100 */ 192 */
101 protected void reportError(DartScanner.Position position, ErrorCode errorCode, 193 protected void reportError(DartScanner.Position position,
102 Object... arguments) { 194 ErrorCode errorCode, Object... arguments) {
103 DartScanner.Location location = ctx.getTokenLocation(); 195 DartScanner.Location location = ctx.getTokenLocation();
104 if (location.getBegin().getPos() <= lastErrorPosition) { 196 if (location.getBegin().getPos() <= lastErrorPosition) {
105 return; 197 return;
106 } 198 }
107 DartCompilationError dartError = new DartCompilationError(ctx.getSource(), l ocation, errorCode, 199 DartCompilationError dartError = new DartCompilationError(ctx.getSource(),
108 arguments); 200 location, errorCode, arguments);
109 lastErrorPosition = position.getPos(); 201 lastErrorPosition = position.getPos();
110 ctx.error(dartError); 202 ctx.error(dartError);
111 } 203 }
112 204
113 /** 205 /**
114 * Even though you pass a 'Position' to {@link #reportError} above, it only us es that to 206 * Even though you pass a 'Position' to {@link #reportError} above, it only
115 * prevent logging more than one error at that position. This method actually uses the passed 207 * uses that to prevent logging more than one error at that position. This
116 * position to create the error event. 208 * method actually uses the passed position to create the error event.
117 */ 209 */
118 protected void reportErrorAtPosition(DartScanner.Position startPosition, 210 protected void reportErrorAtPosition(DartScanner.Position startPosition,
119 DartScanner.Position endPosition, 211 DartScanner.Position endPosition,
120 ErrorCode errorCode, Object... arguments) { 212 ErrorCode errorCode, Object... arguments) {
121 DartScanner.Location location = ctx.getTokenLocation(); 213 DartScanner.Location location = ctx.getTokenLocation();
122 if (location.getBegin().getPos() <= lastErrorPosition) { 214 if (location.getBegin().getPos() <= lastErrorPosition) {
123 return; 215 return;
124 } 216 }
125 DartCompilationError dartError = new DartCompilationError(ctx.getSource(), 217 DartCompilationError dartError = new DartCompilationError(ctx.getSource(),
126 new Location(startPosition, endPosition), errorCode, arguments); 218 new Location(startPosition, endPosition), errorCode, arguments);
127 ctx.error(dartError); 219 ctx.error(dartError);
128 } 220 }
129 221
130 protected void reportUnexpectedToken(DartScanner.Position position, Token expe cted, 222 protected void reportUnexpectedToken(DartScanner.Position position,
131 Token actual) { 223 Token expected, Token actual) {
132 if (expected == Token.EOS) { 224 if (expected == Token.EOS) {
133 reportError(position, ParserErrorCode.EXPECTED_EOS, actual); 225 reportError(position, ParserErrorCode.EXPECTED_EOS, actual);
134 } else if (expected == null) { 226 } else if (expected == null) {
135 reportError(position, ParserErrorCode.UNEXPECTED_TOKEN, actual); 227 reportError(position, ParserErrorCode.UNEXPECTED_TOKEN, actual);
136 } else { 228 } else {
137 reportError(position, ParserErrorCode.EXPECTED_TOKEN, actual, expected); 229 reportError(position, ParserErrorCode.EXPECTED_TOKEN, actual, expected);
138 } 230 }
139 } 231 }
140 232
141 protected void setPeek(int n, Token token) { 233 protected void setPeek(int n, Token token) {
142 assert n == 0; // so far, n is always zero 234 assert n == 0; // so far, n is always zero
143 ctx.replaceNextToken(token); 235 ctx.replaceNextToken(token);
144 } 236 }
145 237
146 protected boolean consume(Token token) { 238 protected boolean consume(Token token) {
147 boolean result = (peek(0) == token); 239 boolean result = (peek(0) == token);
148 assert (result); 240 assert (result);
149 next(); 241 next();
150 return result; 242 return result;
151 } 243 }
152 } 244 }
OLDNEW
« no previous file with comments | « no previous file | compiler/java/com/google/dart/compiler/parser/DartParser.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698