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) { |