1.1 --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Nov 14 08:09:47 2011 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Mon Nov 14 15:11:10 2011 -0800 1.3 @@ -83,12 +83,16 @@ 1.4 /** The name table. */ 1.5 private Names names; 1.6 1.7 + /** End position mappings container */ 1.8 + private final AbstractEndPosTable endPosTable; 1.9 + 1.10 /** Construct a parser from a given scanner, tree factory and log. 1.11 */ 1.12 protected JavacParser(ParserFactory fac, 1.13 Lexer S, 1.14 boolean keepDocComments, 1.15 - boolean keepLineMap) { 1.16 + boolean keepLineMap, 1.17 + boolean keepEndPositions) { 1.18 this.S = S; 1.19 nextToken(); // prime the pump 1.20 this.F = fac.F; 1.21 @@ -110,8 +114,14 @@ 1.22 docComments = keepDocComments ? new HashMap<JCTree,String>() : null; 1.23 this.keepLineMap = keepLineMap; 1.24 this.errorTree = F.Erroneous(); 1.25 + endPosTable = newEndPosTable(keepEndPositions); 1.26 } 1.27 1.28 + protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) { 1.29 + return keepEndPositions 1.30 + ? new SimpleEndPosTable() 1.31 + : new EmptyEndPosTable(); 1.32 + } 1.33 /** Switch: Should generics be recognized? 1.34 */ 1.35 boolean allowGenerics; 1.36 @@ -389,37 +399,21 @@ 1.37 1.38 /* -------- source positions ------- */ 1.39 1.40 - private int errorEndPos = -1; 1.41 - 1.42 private void setErrorEndPos(int errPos) { 1.43 - if (errPos > errorEndPos) 1.44 - errorEndPos = errPos; 1.45 + endPosTable.setErrorEndPos(errPos); 1.46 } 1.47 1.48 - protected int getErrorEndPos() { 1.49 - return errorEndPos; 1.50 + private void storeEnd(JCTree tree, int endpos) { 1.51 + endPosTable.storeEnd(tree, endpos); 1.52 } 1.53 1.54 - /** 1.55 - * Store ending position for a tree. 1.56 - * @param tree The tree. 1.57 - * @param endpos The ending position to associate with the tree. 1.58 - */ 1.59 - protected void storeEnd(JCTree tree, int endpos) {} 1.60 + private <T extends JCTree> T to(T t) { 1.61 + return endPosTable.to(t); 1.62 + } 1.63 1.64 - /** 1.65 - * Store ending position for a tree. The ending position should 1.66 - * be the ending position of the current token. 1.67 - * @param t The tree. 1.68 - */ 1.69 - protected <T extends JCTree> T to(T t) { return t; } 1.70 - 1.71 - /** 1.72 - * Store ending position for a tree. The ending position should 1.73 - * be greater of the ending position of the previous token and errorEndPos. 1.74 - * @param t The tree. 1.75 - */ 1.76 - protected <T extends JCTree> T toP(T t) { return t; } 1.77 + private <T extends JCTree> T toP(T t) { 1.78 + return endPosTable.toP(t); 1.79 + } 1.80 1.81 /** Get the start position for a tree node. The start position is 1.82 * defined to be the position of the first character of the first 1.83 @@ -439,7 +433,7 @@ 1.84 * @param tree The tree node 1.85 */ 1.86 public int getEndPos(JCTree tree) { 1.87 - return Position.NOPOS; 1.88 + return endPosTable.getEndPos(tree); 1.89 } 1.90 1.91 1.92 @@ -1362,7 +1356,7 @@ 1.93 int pos = token.pos; 1.94 nextToken(); 1.95 accept(CLASS); 1.96 - if (token.pos == errorEndPos) { 1.97 + if (token.pos == endPosTable.errorEndPos) { 1.98 // error recovery 1.99 Name name = null; 1.100 if (token.kind == IDENTIFIER) { 1.101 @@ -1542,10 +1536,11 @@ 1.102 /** ParExpression = "(" Expression ")" 1.103 */ 1.104 JCExpression parExpression() { 1.105 + int pos = token.pos; 1.106 accept(LPAREN); 1.107 JCExpression t = parseExpression(); 1.108 accept(RPAREN); 1.109 - return t; 1.110 + return toP(F.at(pos).Parens(t)); 1.111 } 1.112 1.113 /** Block = "{" BlockStatements "}" 1.114 @@ -1661,7 +1656,7 @@ 1.115 // error recovery 1.116 if (token.pos == lastErrPos) 1.117 return stats.toList(); 1.118 - if (token.pos <= errorEndPos) { 1.119 + if (token.pos <= endPosTable.errorEndPos) { 1.120 skip(false, true, true, true); 1.121 lastErrPos = token.pos; 1.122 } 1.123 @@ -2270,7 +2265,7 @@ 1.124 boolean checkForImports = true; 1.125 boolean firstTypeDecl = true; 1.126 while (token.kind != EOF) { 1.127 - if (token.pos <= errorEndPos) { 1.128 + if (token.pos <= endPosTable.errorEndPos) { 1.129 // error recovery 1.130 skip(checkForImports, false, false, false); 1.131 if (token.kind == EOF) 1.132 @@ -2304,6 +2299,7 @@ 1.133 toplevel.docComments = docComments; 1.134 if (keepLineMap) 1.135 toplevel.lineMap = S.getLineMap(); 1.136 + toplevel.endPositions = this.endPosTable; 1.137 return toplevel; 1.138 } 1.139 1.140 @@ -2494,7 +2490,7 @@ 1.141 while (token.kind != RBRACE && token.kind != EOF) { 1.142 defs.appendList(classOrInterfaceBodyDeclaration(enumName, 1.143 false)); 1.144 - if (token.pos <= errorEndPos) { 1.145 + if (token.pos <= endPosTable.errorEndPos) { 1.146 // error recovery 1.147 skip(false, true, true, false); 1.148 } 1.149 @@ -2556,7 +2552,7 @@ 1.150 */ 1.151 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 1.152 accept(LBRACE); 1.153 - if (token.pos <= errorEndPos) { 1.154 + if (token.pos <= endPosTable.errorEndPos) { 1.155 // error recovery 1.156 skip(false, true, false, false); 1.157 if (token.kind == LBRACE) 1.158 @@ -2565,7 +2561,7 @@ 1.159 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 1.160 while (token.kind != RBRACE && token.kind != EOF) { 1.161 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 1.162 - if (token.pos <= errorEndPos) { 1.163 + if (token.pos <= endPosTable.errorEndPos) { 1.164 // error recovery 1.165 skip(false, true, true, false); 1.166 } 1.167 @@ -2697,7 +2693,7 @@ 1.168 defaultValue = null; 1.169 } 1.170 accept(SEMI); 1.171 - if (token.pos <= errorEndPos) { 1.172 + if (token.pos <= endPosTable.errorEndPos) { 1.173 // error recovery 1.174 skip(false, true, false, false); 1.175 if (token.kind == LBRACE) { 1.176 @@ -3028,4 +3024,112 @@ 1.177 allowTWR = true; 1.178 } 1.179 } 1.180 + 1.181 + /* 1.182 + * a functional source tree and end position mappings 1.183 + */ 1.184 + protected class SimpleEndPosTable extends AbstractEndPosTable { 1.185 + 1.186 + private final Map<JCTree, Integer> endPosMap; 1.187 + 1.188 + SimpleEndPosTable() { 1.189 + endPosMap = new HashMap<JCTree, Integer>(); 1.190 + } 1.191 + 1.192 + protected void storeEnd(JCTree tree, int endpos) { 1.193 + endPosMap.put(tree, errorEndPos > endpos ? errorEndPos : endpos); 1.194 + } 1.195 + 1.196 + protected <T extends JCTree> T to(T t) { 1.197 + storeEnd(t, token.endPos); 1.198 + return t; 1.199 + } 1.200 + 1.201 + protected <T extends JCTree> T toP(T t) { 1.202 + storeEnd(t, S.prevToken().endPos); 1.203 + return t; 1.204 + } 1.205 + 1.206 + public int getEndPos(JCTree tree) { 1.207 + Integer value = endPosMap.get(tree); 1.208 + return (value == null) ? Position.NOPOS : value; 1.209 + } 1.210 + 1.211 + public int replaceTree(JCTree oldTree, JCTree newTree) { 1.212 + Integer pos = endPosMap.remove(oldTree); 1.213 + if (pos != null) { 1.214 + endPosMap.put(newTree, pos); 1.215 + return pos; 1.216 + } 1.217 + return Position.NOPOS; 1.218 + } 1.219 + } 1.220 + 1.221 + /* 1.222 + * a default skeletal implementation without any mapping overhead. 1.223 + */ 1.224 + protected class EmptyEndPosTable extends AbstractEndPosTable { 1.225 + 1.226 + protected void storeEnd(JCTree tree, int endpos) { /* empty */ } 1.227 + 1.228 + protected <T extends JCTree> T to(T t) { 1.229 + return t; 1.230 + } 1.231 + 1.232 + protected <T extends JCTree> T toP(T t) { 1.233 + return t; 1.234 + } 1.235 + 1.236 + public int getEndPos(JCTree tree) { 1.237 + return Position.NOPOS; 1.238 + } 1.239 + 1.240 + public int replaceTree(JCTree oldTree, JCTree newTree) { 1.241 + return Position.NOPOS; 1.242 + } 1.243 + 1.244 + } 1.245 + 1.246 + protected abstract class AbstractEndPosTable implements EndPosTable { 1.247 + 1.248 + /** 1.249 + * Store the last error position. 1.250 + */ 1.251 + protected int errorEndPos; 1.252 + 1.253 + /** 1.254 + * Store ending position for a tree, the value of which is the greater 1.255 + * of last error position and the given ending position. 1.256 + * @param tree The tree. 1.257 + * @param endpos The ending position to associate with the tree. 1.258 + */ 1.259 + protected abstract void storeEnd(JCTree tree, int endpos); 1.260 + 1.261 + /** 1.262 + * Store current token's ending position for a tree, the value of which 1.263 + * will be the greater of last error position and the ending position of 1.264 + * the current token. 1.265 + * @param t The tree. 1.266 + */ 1.267 + protected abstract <T extends JCTree> T to(T t); 1.268 + 1.269 + /** 1.270 + * Store current token's ending position for a tree, the value of which 1.271 + * will be the greater of last error position and the ending position of 1.272 + * the previous token. 1.273 + * @param t The tree. 1.274 + */ 1.275 + protected abstract <T extends JCTree> T toP(T t); 1.276 + 1.277 + /** 1.278 + * Set the error position during the parsing phases, the value of which 1.279 + * will be set only if it is greater than the last stored error position. 1.280 + * @param errPos The error position 1.281 + */ 1.282 + protected void setErrorEndPos(int errPos) { 1.283 + if (errPos > errorEndPos) { 1.284 + errorEndPos = errPos; 1.285 + } 1.286 + } 1.287 + } 1.288 }