| /* |
| * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| import com.sun.tools.javac.code.TypeTag; |
| import com.sun.tools.javac.parser.JavacParser; |
| import com.sun.tools.javac.parser.ParserFactory; |
| import com.sun.tools.javac.parser.Tokens.Comment; |
| import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; |
| import com.sun.tools.javac.parser.Tokens.Token; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.CLASS; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.COLON; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.ENUM; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.EOF; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.INTERFACE; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.LPAREN; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.MONKEYS_AT; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.PACKAGE; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.SEMI; |
| import static com.sun.tools.javac.parser.Tokens.TokenKind.VOID; |
| import com.sun.tools.javac.tree.JCTree; |
| import com.sun.tools.javac.tree.JCTree.JCAnnotation; |
| import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; |
| import com.sun.tools.javac.tree.JCTree.JCExpression; |
| import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; |
| import com.sun.tools.javac.tree.JCTree.JCModifiers; |
| import com.sun.tools.javac.tree.JCTree.JCPackageDecl; |
| import com.sun.tools.javac.tree.JCTree.JCStatement; |
| import com.sun.tools.javac.tree.JCTree.JCTypeParameter; |
| import com.sun.tools.javac.tree.JCTree.JCVariableDecl; |
| import com.sun.tools.javac.tree.JCTree.Tag; |
| import static com.sun.tools.javac.tree.JCTree.Tag.IDENT; |
| import com.sun.tools.javac.util.List; |
| import com.sun.tools.javac.util.ListBuffer; |
| import com.sun.tools.javac.util.Name; |
| import com.sun.tools.javac.util.Position; |
| |
| /** |
| * |
| * @author Robert Field |
| */ |
| class TrialParser extends JavacParser { |
| |
| public TrialParser(ParserFactory fac, |
| com.sun.tools.javac.parser.Lexer S, |
| boolean keepDocComments, |
| boolean keepLineMap, |
| boolean keepEndPositions) { |
| super(fac, S, keepDocComments, keepLineMap, keepEndPositions); |
| } |
| |
| @Override |
| public JCCompilationUnit parseCompilationUnit() { |
| Token firstToken = token; |
| JCModifiers mods = null; |
| boolean seenImport = false; |
| boolean seenPackage = false; |
| ListBuffer<JCTree> defs = new ListBuffer<>(); |
| if (token.kind == MONKEYS_AT) { |
| mods = modifiersOpt(); |
| } |
| |
| if (token.kind == PACKAGE) { |
| int packagePos = token.pos; |
| List<JCAnnotation> annotations = List.nil(); |
| seenPackage = true; |
| if (mods != null) { |
| checkNoMods(mods.flags); |
| annotations = mods.annotations; |
| mods = null; |
| } |
| nextToken(); |
| JCExpression pid = qualident(false); |
| accept(SEMI); |
| JCPackageDecl pd = F.at(packagePos).PackageDecl(annotations, pid); |
| attach(pd, firstToken.comment(CommentStyle.JAVADOC)); |
| storeEnd(pd, token.pos); |
| defs.append(pd); |
| } |
| |
| boolean firstTypeDecl = true; |
| while (token.kind != EOF) { |
| if (token.pos > 0 && token.pos <= endPosTable.errorEndPos) { |
| // error recovery |
| skip(true, false, false, false); |
| if (token.kind == EOF) { |
| break; |
| } |
| } |
| if (mods == null && token.kind == IMPORT) { |
| seenImport = true; |
| defs.append(importDeclaration()); |
| break; |
| } else { |
| Comment docComment = token.comment(CommentStyle.JAVADOC); |
| if (firstTypeDecl && !seenImport && !seenPackage) { |
| docComment = firstToken.comment(CommentStyle.JAVADOC); |
| } |
| List<? extends JCTree> udefs = aUnit(mods, docComment); |
| for (JCTree def : udefs) { |
| defs.append(def); |
| } |
| mods = null; |
| firstTypeDecl = false; |
| break; |
| } |
| } |
| List<JCTree> rdefs = defs.toList(); |
| class TrialUnit extends JCCompilationUnit { |
| |
| public TrialUnit(List<JCTree> defs) { |
| super(defs); |
| } |
| } |
| JCCompilationUnit toplevel = new TrialUnit(rdefs); |
| if (rdefs.isEmpty()) { |
| storeEnd(toplevel, S.prevToken().endPos); |
| } |
| toplevel.lineMap = S.getLineMap(); |
| this.endPosTable.setParser(null); // remove reference to parser |
| toplevel.endPositions = this.endPosTable; |
| return toplevel; |
| } |
| |
| List<? extends JCTree> aUnit(JCModifiers pmods, Comment dc) { |
| switch (token.kind) { |
| case EOF: |
| return List.nil(); |
| case RBRACE: |
| case CASE: |
| case DEFAULT: |
| // These are illegal, fall through to handle as illegal statement |
| case LBRACE: |
| case IF: |
| case FOR: |
| case WHILE: |
| case DO: |
| case TRY: |
| case SWITCH: |
| case SYNCHRONIZED: |
| case RETURN: |
| case THROW: |
| case BREAK: |
| case CONTINUE: |
| case SEMI: |
| case ELSE: |
| case FINALLY: |
| case CATCH: |
| case ASSERT: |
| return List.<JCTree>of(parseStatement()); |
| default: |
| JCModifiers mods = modifiersOpt(pmods); |
| if (token.kind == CLASS |
| || token.kind == INTERFACE |
| || token.kind == ENUM) { |
| return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); |
| } else { |
| int pos = token.pos; |
| List<JCTypeParameter> typarams = typeParametersOpt(); |
| // if there are type parameters but no modifiers, save the start |
| // position of the method in the modifiers. |
| if (typarams.nonEmpty() && mods.pos == Position.NOPOS) { |
| mods.pos = pos; |
| storeEnd(mods, pos); |
| } |
| List<JCAnnotation> annosAfterParams = annotationsOpt(Tag.ANNOTATION); |
| |
| if (annosAfterParams.nonEmpty()) { |
| checkAnnotationsAfterTypeParams(annosAfterParams.head.pos); |
| mods.annotations = mods.annotations.appendList(annosAfterParams); |
| if (mods.pos == Position.NOPOS) { |
| mods.pos = mods.annotations.head.pos; |
| } |
| } |
| |
| Token prevToken = token; |
| pos = token.pos; |
| JCExpression t; |
| boolean isVoid = token.kind == VOID; |
| if (isVoid) { |
| t = to(F.at(pos).TypeIdent(TypeTag.VOID)); |
| nextToken(); |
| } else { |
| // return type of method, declared type of variable, or an expression |
| t = term(EXPR | TYPE); |
| } |
| if (token.kind == COLON && t.hasTag(IDENT)) { |
| // labelled statement |
| nextToken(); |
| JCStatement stat = parseStatement(); |
| return List.<JCTree>of(F.at(pos).Labelled(prevToken.name(), stat)); |
| } else if ((isVoid || (lastmode & TYPE) != 0) && LAX_IDENTIFIER.accepts(token.kind)) { |
| // we have "Type Ident", so we can assume it is variable or method declaration |
| pos = token.pos; |
| Name name = ident(); |
| if (token.kind == LPAREN) { |
| // method declaration |
| //mods.flags |= Flags.STATIC; |
| return List.of(methodDeclaratorRest( |
| pos, mods, t, name, typarams, |
| false, isVoid, dc)); |
| } else if (!isVoid && typarams.isEmpty()) { |
| // variable declaration |
| //mods.flags |= Flags.STATIC; |
| List<JCTree> defs |
| = variableDeclaratorsRest(pos, mods, t, name, false, dc, |
| new ListBuffer<JCTree>()).toList(); |
| accept(SEMI); |
| storeEnd(defs.last(), S.prevToken().endPos); |
| return defs; |
| } else { |
| // malformed declaration, return error |
| pos = token.pos; |
| List<JCTree> err = isVoid |
| ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, t, typarams, |
| List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) |
| : null; |
| return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN)); |
| } |
| } else if (!typarams.isEmpty()) { |
| // type parameters on non-variable non-method -- error |
| return List.<JCTree>of(syntaxError(token.pos, "illegal.start.of.type")); |
| } else { |
| // expression-statement or expression to evaluate |
| accept(SEMI); |
| JCExpressionStatement expr = toP(F.at(pos).Exec(t)); |
| return List.<JCTree>of(expr); |
| } |
| |
| } |
| } |
| } |
| } |