1 /* 2 * Copyright (c) 2015, 2018, 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 24 import com.sun.tools.javac.code.Source.Feature; 25 import com.sun.tools.javac.code.TypeTag; 26 import com.sun.tools.javac.parser.JavacParser; 27 import com.sun.tools.javac.parser.ParserFactory; 28 import com.sun.tools.javac.parser.Tokens.Comment; 29 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; 30 import com.sun.tools.javac.parser.Tokens.Token; 31 import static com.sun.tools.javac.parser.Tokens.TokenKind.CLASS; 32 import static com.sun.tools.javac.parser.Tokens.TokenKind.COLON; 33 import static com.sun.tools.javac.parser.Tokens.TokenKind.ENUM; 34 import static com.sun.tools.javac.parser.Tokens.TokenKind.EOF; 35 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; 36 import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE; 37 import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN; 38 import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT; 39 import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE; 40 import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI; 41 import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID; 42 import com.sun.tools.javac.tree.JCTree; 43 import com.sun.tools.javac.tree.JCTree.JCAnnotation; 44 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 45 import com.sun.tools.javac.tree.JCTree.JCExpression; 46 import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; 47 import com.sun.tools.javac.tree.JCTree.JCModifiers; 48 import com.sun.tools.javac.tree.JCTree.JCPackageDecl; 49 import com.sun.tools.javac.tree.JCTree.JCStatement; 50 import com.sun.tools.javac.tree.JCTree.JCTypeParameter; 51 import com.sun.tools.javac.tree.JCTree.JCVariableDecl; 52 import com.sun.tools.javac.tree.JCTree.Tag; 53 import static com.sun.tools.javac.tree.JCTree.Tag.IDENT; 54 import com.sun.tools.javac.util.List; 55 import com.sun.tools.javac.util.ListBuffer; 56 import com.sun.tools.javac.util.Name; 57 import com.sun.tools.javac.util.Position; 58 import com.sun.tools.javac.resources.CompilerProperties.Errors; 59 60 /** 61 * 62 * @author Robert Field 63 */ 64 class TrialParser extends JavacParser { 65 TrialParser(ParserFactory fac, com.sun.tools.javac.parser.Lexer S, boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions)66 public TrialParser(ParserFactory fac, 67 com.sun.tools.javac.parser.Lexer S, 68 boolean keepDocComments, 69 boolean keepLineMap, 70 boolean keepEndPositions) { 71 super(fac, S, keepDocComments, keepLineMap, keepEndPositions); 72 } 73 74 @Override parseCompilationUnit()75 public JCCompilationUnit parseCompilationUnit() { 76 Token firstToken = token; 77 JCModifiers mods = null; 78 boolean seenImport = false; 79 boolean seenPackage = false; 80 ListBuffer<JCTree> defs = new ListBuffer<>(); 81 if (token.kind == MONKEYS_AT) { 82 mods = modifiersOpt(); 83 } 84 85 if (token.kind == PACKAGE) { 86 int packagePos = token.pos; 87 List<JCAnnotation> annotations = List.nil(); 88 seenPackage = true; 89 if (mods != null) { 90 checkNoMods(mods.flags); 91 annotations = mods.annotations; 92 mods = null; 93 } 94 nextToken(); 95 JCExpression pid = qualident(false); 96 accept(SEMI); 97 JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid); 98 attach(pd, firstToken.comment(CommentStyle.JAVADOC)); 99 storeEnd(pd, token.pos); 100 defs.append(pd); 101 } 102 103 boolean firstTypeDecl = true; 104 while (token.kind != EOF) { 105 if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { 106 // error recovery 107 skip(true, false, false, false); 108 if (token.kind == EOF) { 109 break; 110 } 111 } 112 if (mods == null && token.kind == IMPORT) { 113 seenImport = true; 114 defs.append(importDeclaration()); 115 break; 116 } else { 117 Comment docComment = token.comment(CommentStyle.JAVADOC); 118 if (firstTypeDecl && !seenImport && !seenPackage) { 119 docComment = firstToken.comment(CommentStyle.JAVADOC); 120 } 121 List<? extends JCTree> udefs = aUnit(mods, docComment); 122 for (JCTree def : udefs) { 123 defs.append(def); 124 } 125 mods = null; 126 firstTypeDecl = false; 127 break; 128 } 129 } 130 List<JCTree> rdefs = defs.toList(); 131 class TrialUnit extends JCCompilationUnit { 132 133 public TrialUnit(List<JCTree> defs) { 134 super(defs); 135 } 136 } 137 JCCompilationUnit toplevel = new TrialUnit(rdefs); 138 if (rdefs.isEmpty()) { 139 storeEnd(toplevel, S.prevToken().endPos); 140 } 141 toplevel.lineMap = S.getLineMap(); 142 this.endPosTable.setParser(null); // remove reference to parser 143 toplevel.endPositions = this.endPosTable; 144 return toplevel; 145 } 146 aUnit(JCModifiers pmods, Comment dc)147 List<? extends JCTree> aUnit(JCModifiers pmods, Comment dc) { 148 switch (token.kind) { 149 case EOF: 150 return List.nil(); 151 case RBRACE: 152 case CASE: 153 case DEFAULT: 154 // These are illegal, fall through to handle as illegal statement 155 case LBRACE: 156 case IF: 157 case FOR: 158 case WHILE: 159 case DO: 160 case TRY: 161 case SWITCH: 162 case SYNCHRONIZED: 163 case RETURN: 164 case THROW: 165 case BREAK: 166 case CONTINUE: 167 case SEMI: 168 case ELSE: 169 case FINALLY: 170 case CATCH: 171 case ASSERT: 172 return List.<JCTree>of(parseStatement()); 173 default: 174 JCModifiers mods = modifiersOpt(pmods); 175 if (token.kind == CLASS 176 || token.kind == INTERFACE 177 || token.kind == ENUM) { 178 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 179 } else { 180 int pos = token.pos; 181 List<JCTypeParameter> typarams = typeParametersOpt(); 182 // if there are type parameters but no modifiers, save the start 183 // position of the method in the modifiers. 184 if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { 185 mods.pos = pos; 186 storeEnd(mods, pos); 187 } 188 List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); 189 190 if (annosAfterParams.nonEmpty()) { 191 checkSourceLevel(annosAfterParams.head.pos, Feature.ANNOTATIONS_AFTER_TYPE_PARAMS); 192 mods.annotations = mods.annotations.appendList(annosAfterParams); 193 if (mods.pos == Position.NOPOS) { 194 mods.pos = mods.annotations.head.pos; 195 } 196 } 197 198 Token prevToken = token; 199 pos = token.pos; 200 JCExpression t; 201 boolean isVoid = token.kind == VOID; 202 if (isVoid) { 203 t = to(F.at(pos).TypeIdent(TypeTag.VOID)); 204 nextToken(); 205 } else { 206 // return type of method, declared type of variable, or an expression 207 t = term(EXPR | TYPE); 208 } 209 if (token.kind == COLON && t.hasTag(IDENT)) { 210 // labelled statement 211 nextToken(); 212 JCStatement stat = parseStatement(); 213 return List.<JCTree>of(F.at(pos).Labelled(prevToken.name(), stat)); 214 } else if ((isVoid || (lastmode & TYPE) != 0) && LAX_IDENTIFIER.accepts(token.kind)) { 215 // we have "Type Ident", so we can assume it is variable or method declaration 216 pos = token.pos; 217 Name name = ident(); 218 if (token.kind == LPAREN) { 219 // method declaration 220 //mods.flags |= Flags.STATIC; 221 return List.of(methodDeclaratorRest( 222 pos, mods, t, name, typarams, 223 false, isVoid, dc)); 224 } else if (!isVoid && typarams.isEmpty()) { 225 // variable declaration 226 //mods.flags |= Flags.STATIC; 227 List<JCTree> defs 228 = variableDeclaratorsRest(pos, mods, t, name, false, dc, 229 new ListBuffer<JCTree>(), true).toList(); 230 accept(SEMI); 231 storeEnd(defs.last(), S.prevToken().endPos); 232 return defs; 233 } else { 234 // malformed declaration, return error 235 pos = token.pos; 236 List<JCTree> err = isVoid 237 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, t, typarams, 238 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 239 : null; 240 return List.<JCTree>of(syntaxError(token.pos, err, Errors.Expected(LPAREN))); 241 } 242 } else if (!typarams.isEmpty()) { 243 // type parameters on non-variable non-method -- error 244 return List.<JCTree>of(syntaxError(token.pos, Errors.IllegalStartOfType)); 245 } else { 246 // expression-statement or expression to evaluate 247 accept(SEMI); 248 JCExpressionStatement expr = toP(F.at(pos).Exec(t)); 249 return List.<JCTree>of(expr); 250 } 251 252 } 253 } 254 } 255 } 256