src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 49076 1d879babed52
parent 48935 03ae177c26b0
child 49152 e38b6a7f65ee
equal deleted inserted replaced
49075:1fd4d6068f54 49076:1d879babed52
    33 
    33 
    34 import com.sun.tools.javac.code.*;
    34 import com.sun.tools.javac.code.*;
    35 import com.sun.tools.javac.code.Source.Feature;
    35 import com.sun.tools.javac.code.Source.Feature;
    36 import com.sun.tools.javac.parser.Tokens.*;
    36 import com.sun.tools.javac.parser.Tokens.*;
    37 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    37 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
    38 import com.sun.tools.javac.resources.CompilerProperties;
       
    39 import com.sun.tools.javac.resources.CompilerProperties.Errors;
    38 import com.sun.tools.javac.resources.CompilerProperties.Errors;
    40 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
    39 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
    41 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
    40 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
    42 import com.sun.tools.javac.tree.*;
    41 import com.sun.tools.javac.tree.*;
    43 import com.sun.tools.javac.tree.JCTree.*;
    42 import com.sun.tools.javac.tree.JCTree.*;
    44 import com.sun.tools.javac.util.*;
    43 import com.sun.tools.javac.util.*;
    45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    44 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
    46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
       
    47 import com.sun.tools.javac.util.JCDiagnostic.Error;
    45 import com.sun.tools.javac.util.JCDiagnostic.Error;
    48 import com.sun.tools.javac.util.JCDiagnostic.Warning;
       
    49 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
    46 import com.sun.tools.javac.util.JCDiagnostic.Fragment;
    50 import com.sun.tools.javac.util.List;
    47 import com.sun.tools.javac.util.List;
    51 
    48 
    52 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
    49 import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
    53 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
    50 import static com.sun.tools.javac.parser.Tokens.TokenKind.ASSERT;
    56 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
    53 import static com.sun.tools.javac.parser.Tokens.TokenKind.EQ;
    57 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
    54 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
    58 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
    55 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
    59 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
    56 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
    60 import static com.sun.tools.javac.tree.JCTree.Tag.*;
    57 import static com.sun.tools.javac.tree.JCTree.Tag.*;
       
    58 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.ImplicitAndExplicitNotAllowed;
       
    59 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndExplicitNotAllowed;
       
    60 import static com.sun.tools.javac.resources.CompilerProperties.Fragments.VarAndImplicitNotAllowed;
    61 
    61 
    62 /** The parser maps a token sequence into an abstract syntax
    62 /** The parser maps a token sequence into an abstract syntax
    63  *  tree. It operates by recursive descent, with code derived
    63  *  tree. It operates by recursive descent, with code derived
    64  *  systematically from an LL(1) grammar. For efficiency reasons, an
    64  *  systematically from an LL(1) grammar. For efficiency reasons, an
    65  *  operator precedence scheme is used for parsing binary operation
    65  *  operator precedence scheme is used for parsing binary operation
  1671 
  1671 
  1672     enum ParensResult {
  1672     enum ParensResult {
  1673         CAST,
  1673         CAST,
  1674         EXPLICIT_LAMBDA,
  1674         EXPLICIT_LAMBDA,
  1675         IMPLICIT_LAMBDA,
  1675         IMPLICIT_LAMBDA,
  1676         IMPLICIT_LAMBDA_ALL_VAR,
       
  1677         BAD_LAMBDA,
       
  1678         PARENS
  1676         PARENS
  1679     }
  1677     }
  1680 
  1678 
  1681     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1679     JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) {
  1682         List<JCVariableDecl> params = explicitParams ?
  1680         List<JCVariableDecl> params = explicitParams ?
  1683                 formalParameters(true) :
  1681                 formalParameters(true) :
  1684                 implicitParameters(hasParens);
  1682                 implicitParameters(hasParens);
  1685 
       
  1686         if (explicitParams) {
  1683         if (explicitParams) {
  1687             LambdaClassfier lambdaClassfier = new LambdaClassfier();
  1684             LambdaClassifier lambdaClassifier = new LambdaClassifier();
  1688             for (JCVariableDecl param: params) {
  1685             for (JCVariableDecl param: params) {
  1689                 if (param.vartype != null &&
  1686                 if (param.vartype != null &&
  1690                         isRestrictedLocalVarTypeName(param.vartype) &&
  1687                         isRestrictedLocalVarTypeName(param.vartype) &&
  1691                         param.vartype.hasTag(TYPEARRAY)) {
  1688                         param.vartype.hasTag(TYPEARRAY)) {
  1692                     log.error(DiagnosticFlag.SYNTAX, param.pos, Errors.VarNotAllowedArray);
  1689                     log.error(DiagnosticFlag.SYNTAX, param.pos, Errors.VarNotAllowedArray);
  1693                 }
  1690                 }
  1694                 if (param.vartype != null && param.name != names.empty) {
  1691                 lambdaClassifier.addParameter(param);
  1695                     if (isRestrictedLocalVarTypeName(param.vartype)) {
  1692                 if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
  1696                         lambdaClassfier.addImplicitVarParameter();
       
  1697                     } else {
       
  1698                         lambdaClassfier.addExplicitParameter();
       
  1699                     }
       
  1700                 }
       
  1701                 if (param.vartype == null && param.name != names.empty ||
       
  1702                     param.vartype != null && param.name == names.empty) {
       
  1703                     lambdaClassfier.addImplicitParameter();
       
  1704                 }
       
  1705                 if (lambdaClassfier.result() == ParensResult.BAD_LAMBDA) {
       
  1706                     break;
  1693                     break;
  1707                 }
  1694                 }
  1708             }
  1695             }
  1709             if (lambdaClassfier.diagFragment != null) {
  1696             if (lambdaClassifier.diagFragment != null) {
  1710                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassfier.diagFragment));
  1697                 log.error(DiagnosticFlag.SYNTAX, pos, Errors.InvalidLambdaParameterDeclaration(lambdaClassifier.diagFragment));
  1711             }
  1698             }
  1712         }
  1699         }
  1713         return lambdaExpressionOrStatementRest(params, pos);
  1700         return lambdaExpressionOrStatementRest(params, pos);
  1714     }
  1701     }
  1715 
  1702 
  1716     class LambdaClassfier {
  1703     enum LambdaParameterKind {
  1717         ParensResult kind; //ParensResult.EXPLICIT_LAMBDA;
  1704         EXPLICIT(0),
       
  1705         IMPLICIT(1),
       
  1706         VAR(2),
       
  1707         ERROR(-1);
       
  1708 
       
  1709         private final int index;
       
  1710 
       
  1711         LambdaParameterKind(int index) {
       
  1712             this.index = index;
       
  1713         }
       
  1714     }
       
  1715 
       
  1716     private final static Fragment[][] decisionTable = new Fragment[][]{
       
  1717         /*              EXPLICIT                         IMPLICIT                         VAR  */
       
  1718         /* EXPLICIT */ {null,                            ImplicitAndExplicitNotAllowed,   VarAndExplicitNotAllowed},
       
  1719         /* IMPLICIT */ {ImplicitAndExplicitNotAllowed,   null,                            VarAndImplicitNotAllowed},
       
  1720         /* VAR      */ {VarAndExplicitNotAllowed,        VarAndImplicitNotAllowed,        null}
       
  1721     };
       
  1722 
       
  1723     class LambdaClassifier {
       
  1724 
       
  1725         LambdaParameterKind kind;
  1718         Fragment diagFragment;
  1726         Fragment diagFragment;
  1719         List<JCVariableDecl> params;
  1727         List<JCVariableDecl> params;
  1720 
  1728 
  1721         void addExplicitParameter() {
  1729         void addParameter(JCVariableDecl param) {
  1722             reduce(ParensResult.EXPLICIT_LAMBDA);
  1730             if (param.vartype != null && param.name != names.empty) {
  1723         }
  1731                 if (isRestrictedLocalVarTypeName(param.vartype)) {
  1724 
  1732                     reduce(LambdaParameterKind.VAR);
  1725         void addImplicitVarParameter() {
  1733                 } else {
  1726            reduce(ParensResult.IMPLICIT_LAMBDA_ALL_VAR);
  1734                     reduce(LambdaParameterKind.EXPLICIT);
  1727         }
  1735                 }
  1728 
  1736             }
  1729         void addImplicitParameter() {
  1737             if (param.vartype == null && param.name != names.empty ||
  1730             reduce(ParensResult.IMPLICIT_LAMBDA);
  1738                 param.vartype != null && param.name == names.empty) {
  1731         }
  1739                 reduce(LambdaParameterKind.IMPLICIT);
  1732 
  1740             }
  1733         private void reduce(ParensResult newKind) {
  1741         }
       
  1742 
       
  1743         private void reduce(LambdaParameterKind newKind) {
  1734             if (kind == null) {
  1744             if (kind == null) {
  1735                 kind = newKind;
  1745                 kind = newKind;
  1736             } else if (kind != newKind && kind != ParensResult.BAD_LAMBDA) {
  1746             } else if (kind != newKind && kind != LambdaParameterKind.ERROR) {
  1737                 ParensResult currentKind = kind;
  1747                 LambdaParameterKind currentKind = kind;
  1738                 kind = ParensResult.BAD_LAMBDA;
  1748                 kind = LambdaParameterKind.ERROR;
  1739                 switch (currentKind) {
  1749                 diagFragment = decisionTable[currentKind.index][newKind.index];
  1740                     case EXPLICIT_LAMBDA:
  1750             }
  1741                         if (newKind == ParensResult.IMPLICIT_LAMBDA) {
  1751         }
  1742                             diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
  1752 
  1743                         } else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
  1753         LambdaParameterKind result() {
  1744                             diagFragment = Fragments.VarAndExplicitNotAllowed;
       
  1745                         }
       
  1746                         break;
       
  1747                     case IMPLICIT_LAMBDA:
       
  1748                         if (newKind == ParensResult.EXPLICIT_LAMBDA) {
       
  1749                             diagFragment = Fragments.ImplicitAndExplicitNotAllowed;
       
  1750                         } else if (newKind == ParensResult.IMPLICIT_LAMBDA_ALL_VAR) {
       
  1751                             diagFragment = Fragments.VarAndImplicitNotAllowed;
       
  1752                         }
       
  1753                         break;
       
  1754                     case IMPLICIT_LAMBDA_ALL_VAR:
       
  1755                         if (newKind == ParensResult.EXPLICIT_LAMBDA) {
       
  1756                             diagFragment = Fragments.VarAndExplicitNotAllowed;
       
  1757                         } else if (newKind == ParensResult.IMPLICIT_LAMBDA) {
       
  1758                             diagFragment = Fragments.VarAndImplicitNotAllowed;
       
  1759                         }
       
  1760                         break;
       
  1761                     default:
       
  1762                         throw new AssertionError("unexpected option for field kind");
       
  1763                 }
       
  1764             }
       
  1765         }
       
  1766 
       
  1767         ParensResult result() {
       
  1768             return kind;
  1754             return kind;
  1769         }
  1755         }
  1770     }
  1756     }
  1771 
  1757 
  1772     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {
  1758     JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) {