TrialParser.java revision 2797:52227644abfa
1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import com.sun.tools.javac.code.TypeTag; 25import com.sun.tools.javac.parser.JavacParser; 26import com.sun.tools.javac.parser.ParserFactory; 27import com.sun.tools.javac.parser.Tokens.Comment; 28import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; 29import com.sun.tools.javac.parser.Tokens.Token; 30import static com.sun.tools.javac.parser.Tokens.TokenKind.CLASS; 31import static com.sun.tools.javac.parser.Tokens.TokenKind.COLON; 32import static com.sun.tools.javac.parser.Tokens.TokenKind.ENUM; 33import static com.sun.tools.javac.parser.Tokens.TokenKind.EOF; 34import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; 35import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE; 36import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN; 37import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT; 38import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE; 39import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI; 40import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID; 41import com.sun.tools.javac.tree.JCTree; 42import com.sun.tools.javac.tree.JCTree.JCAnnotation; 43import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 44import com.sun.tools.javac.tree.JCTree.JCExpression; 45import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; 46import com.sun.tools.javac.tree.JCTree.JCModifiers; 47import com.sun.tools.javac.tree.JCTree.JCPackageDecl; 48import com.sun.tools.javac.tree.JCTree.JCStatement; 49import com.sun.tools.javac.tree.JCTree.JCTypeParameter; 50import com.sun.tools.javac.tree.JCTree.JCVariableDecl; 51import com.sun.tools.javac.tree.JCTree.Tag; 52import static com.sun.tools.javac.tree.JCTree.Tag.IDENT; 53import com.sun.tools.javac.util.List; 54import com.sun.tools.javac.util.ListBuffer; 55import com.sun.tools.javac.util.Name; 56import com.sun.tools.javac.util.Position; 57 58/** 59 * 60 * @author Robert Field 61 */ 62class TrialParser extends JavacParser { 63 64 public TrialParser(ParserFactory fac, 65 com.sun.tools.javac.parser.Lexer S, 66 boolean keepDocComments, 67 boolean keepLineMap, 68 boolean keepEndPositions) { 69 super(fac, S, keepDocComments, keepLineMap, keepEndPositions); 70 } 71 72 @Override 73 public JCCompilationUnit parseCompilationUnit() { 74 Token firstToken = token; 75 JCModifiers mods = null; 76 boolean seenImport = false; 77 boolean seenPackage = false; 78 ListBuffer<JCTree> defs = new ListBuffer<>(); 79 if (token.kind == MONKEYS_AT) { 80 mods = modifiersOpt(); 81 } 82 83 if (token.kind == PACKAGE) { 84 int packagePos = token.pos; 85 List<JCAnnotation> annotations = List.nil(); 86 seenPackage = true; 87 if (mods != null) { 88 checkNoMods(mods.flags); 89 annotations = mods.annotations; 90 mods = null; 91 } 92 nextToken(); 93 JCExpression pid = qualident(false); 94 accept(SEMI); 95 JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid); 96 attach(pd, firstToken.comment(CommentStyle.JAVADOC)); 97 storeEnd(pd, token.pos); 98 defs.append(pd); 99 } 100 101 boolean firstTypeDecl = true; 102 while (token.kind != EOF) { 103 if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { 104 // error recovery 105 skip(true, false, false, false); 106 if (token.kind == EOF) { 107 break; 108 } 109 } 110 if (mods == null && token.kind == IMPORT) { 111 seenImport = true; 112 defs.append(importDeclaration()); 113 break; 114 } else { 115 Comment docComment = token.comment(CommentStyle.JAVADOC); 116 if (firstTypeDecl && !seenImport && !seenPackage) { 117 docComment = firstToken.comment(CommentStyle.JAVADOC); 118 } 119 List<? extends JCTree> udefs = aUnit(mods, docComment); 120 for (JCTree def : udefs) { 121 defs.append(def); 122 } 123 mods = null; 124 firstTypeDecl = false; 125 break; 126 } 127 } 128 List<JCTree> rdefs = defs.toList(); 129 class TrialUnit extends JCCompilationUnit { 130 131 public TrialUnit(List<JCTree> defs) { 132 super(defs); 133 } 134 } 135 JCCompilationUnit toplevel = new TrialUnit(rdefs); 136 if (rdefs.isEmpty()) { 137 storeEnd(toplevel, S.prevToken().endPos); 138 } 139 toplevel.lineMap = S.getLineMap(); 140 this.endPosTable.setParser(null); // remove reference to parser 141 toplevel.endPositions = this.endPosTable; 142 return toplevel; 143 } 144 145 List<? extends JCTree> aUnit(JCModifiers pmods, Comment dc) { 146 switch (token.kind) { 147 case EOF: 148 return List.nil(); 149 case RBRACE: 150 case CASE: 151 case DEFAULT: 152 // These are illegal, fall through to handle as illegal statement 153 case LBRACE: 154 case IF: 155 case FOR: 156 case WHILE: 157 case DO: 158 case TRY: 159 case SWITCH: 160 case SYNCHRONIZED: 161 case RETURN: 162 case THROW: 163 case BREAK: 164 case CONTINUE: 165 case SEMI: 166 case ELSE: 167 case FINALLY: 168 case CATCH: 169 case ASSERT: 170 return List.<JCTree>of(parseStatement()); 171 default: 172 JCModifiers mods = modifiersOpt(pmods); 173 if (token.kind == CLASS 174 || token.kind == INTERFACE 175 || token.kind == ENUM) { 176 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 177 } else { 178 int pos = token.pos; 179 List<JCTypeParameter> typarams = typeParametersOpt(); 180 // if there are type parameters but no modifiers, save the start 181 // position of the method in the modifiers. 182 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 183 mods.pos = pos; 184 storeEnd(mods, pos); 185 } 186 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); 187 188 if (annosAfterParams.nonEmpty()) { 189 checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); 190 mods.annotations = mods.annotations.appendList(annosAfterParams); 191 if (mods.pos == Position.NOPOS) { 192 mods.pos = mods.annotations.head.pos; 193 } 194 } 195 196 Token prevToken = token; 197 pos = token.pos; 198 JCExpression t; 199 boolean isVoid = token.kind == VOID; 200 if (isVoid) { 201 t = to(F.at(pos).TypeIdent(TypeTag.VOID)); 202 nextToken(); 203 } else { 204 // return type of method, declared type of variable, or an expression 205 t = term(EXPR | TYPE); 206 } 207 if (token.kind == COLON && t.hasTag(IDENT)) { 208 // labelled statement 209 nextToken(); 210 JCStatement stat = parseStatement(); 211 return List.<JCTree>of(F.at(pos).Labelled(prevToken.name(), stat)); 212 } else if ((isVoid || (lastmode & TYPE) != 0) && LAX_IDENTIFIER.accepts(token.kind)) { 213 // we have "Type Ident", so we can assume it is variable or method declaration 214 pos = token.pos; 215 Name name = ident(); 216 if (token.kind == LPAREN) { 217 // method declaration 218 //mods.flags |= Flags.STATIC; 219 return List.of(methodDeclaratorRest( 220 pos, mods, t, name, typarams, 221 false, isVoid, dc)); 222 } else if (!isVoid && typarams.isEmpty()) { 223 // variable declaration 224 //mods.flags |= Flags.STATIC; 225 List<JCTree> defs 226 = variableDeclaratorsRest(pos, mods, t, name, false, dc, 227 new ListBuffer<JCTree>()).toList(); 228 accept(SEMI); 229 storeEnd(defs.last(), S.prevToken().endPos); 230 return defs; 231 } else { 232 // malformed declaration, return error 233 pos = token.pos; 234 List<JCTree> err = isVoid 235 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, t, typarams, 236 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 237 : null; 238 return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN)); 239 } 240 } else if (!typarams.isEmpty()) { 241 // type parameters on non-variable non-method -- error 242 return List.<JCTree>of(syntaxError(token.pos, "illegal.start.of.type")); 243 } else { 244 // expression-statement or expression to evaluate 245 accept(SEMI); 246 JCExpressionStatement expr = toP(F.at(pos).Exec(t)); 247 return List.<JCTree>of(expr); 248 } 249 250 } 251 } 252 } 253} 254