Skip to content

Commit

Permalink
Polish scanner + parser implementation of sealed types. (eclipse-jdt#…
Browse files Browse the repository at this point in the history
  • Loading branch information
srikanth-sankaran authored and gayanper committed Sep 7, 2024
1 parent 860bac0 commit 73a5099
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 42 deletions.
11 changes: 5 additions & 6 deletions org.eclipse.jdt.core.compiler.batch/grammar/java.g
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ Goal ::= '->' YieldStatement
Goal ::= '->' SwitchLabelCaseLhs
-- JEP 409 Sealed types Reconnaissance mission.
Goal ::= RestrictedIdentifiersealed Modifiersopt
Goal ::= RestrictedIdentifierpermits PermittedSubtypes
Goal ::= RestrictedIdentifierpermits PermittedTypes
-- jsr 427 --
Goal ::= BeginCaseElement Pattern
Goal ::= RestrictedIdentifierWhen Expression
Expand Down Expand Up @@ -2412,14 +2412,14 @@ ClassHeaderImplementsopt ::= $empty
ClassHeaderImplementsopt -> ClassHeaderImplements
/:$readableName ClassHeaderImplements:/

-- Production name hardcoded in parser. Must be ::= and not ->
PermittedSubtypes ::= ClassTypeList
/:$readableName PermittedSubtypes:/
-- Production name hardcoded in scanner. Must be ::= and not ->
PermittedTypes ::= ClassTypeList
/:$readableName PermittedTypes:/

PermittedTypesopt -> $empty
PermittedTypesopt ::= RestrictedIdentifierpermits ClassTypeList
/.$putCase consumePermittedTypes(); $break ./
/:$readableName PermittedTypes:/
/:$readableName PermittedTypesopt:/
/:$compliance 17:/

InterfaceMemberDeclarationsopt ::= $empty
Expand Down Expand Up @@ -3206,4 +3206,3 @@ UNDERSCORE ::= '_'
$end
-- need a carriage return after the $end


Original file line number Diff line number Diff line change
Expand Up @@ -4765,10 +4765,9 @@ protected void consumeInterfaceHeaderName1() {
}
protected void consumePermittedTypes() {
int length = this.astLengthStack[this.astLengthPtr--];
//permitted types
this.astPtr -= length;
TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
typeDecl.restrictedIdentifierStart= this.intStack[this.intPtr--];
typeDecl.restrictedIdentifierStart = this.intStack[this.intPtr--];
System.arraycopy(
this.astStack,
this.astPtr + 1,
Expand All @@ -4779,7 +4778,7 @@ protected void consumePermittedTypes() {
rejectIllegalTypeAnnotations(typeReference);
}
typeDecl.bodyStart = typeDecl.permittedTypes[length-1].sourceEnd + 1;
this.listLength = 0; // reset after having read super-interfaces
this.listLength = 0; // reset after having read permitted types.
// recovery
if (this.currentElement != null) {
this.lastCheckPoint = typeDecl.bodyStart;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.internal.compiler.CompilationResult;
Expand Down Expand Up @@ -3445,7 +3443,7 @@ else if ((data[index] == 'o')
&& (data[++index] == 'd')
&& !ScannerHelper.isJavaIdentifierPart(data[++index])) {
this.currentPosition += 7;
int t = disambiguatesRestrictedIdentifierWithLookAhead(x-> !isInModuleDeclaration() && this.sourceLevel >= ClassFileConstants.JDK17, TokenNamenon_sealed, Goal.RestrictedIdentifierSealedGoal);
int t = disambiguatesRestrictedIdentifierWithLookAhead(TokenNamenon_sealed);
if (t == TokenNamenon_sealed) {
return TokenNamenon_sealed;
} else {
Expand Down Expand Up @@ -3527,11 +3525,9 @@ else if ((data[index] == 'o')
&& (data[++index] == 'i')
&& (data[++index] == 't')
&& (data[++index] == 's')) {
return disambiguatesRestrictedIdentifierWithLookAhead(x -> !isInModuleDeclaration() && this.sourceLevel >= ClassFileConstants.JDK17,
TokenNameRestrictedIdentifierpermits,
Goal.RestrictedIdentifierPermitsGoal);
return disambiguatesRestrictedIdentifierWithLookAhead(TokenNameRestrictedIdentifierpermits);
} else
return TokenNameIdentifier;
return TokenNameIdentifier;
}
case 8 :
if (areRestrictedModuleKeywordsActive()
Expand Down Expand Up @@ -3631,9 +3627,7 @@ else if ((data[index] == 'c')
&& (data[++index] == 'l')
&& (data[++index] == 'e')
&& (data[++index] == 'd')) {
return disambiguatesRestrictedIdentifierWithLookAhead(x -> !isInModuleDeclaration() && this.sourceLevel >= ClassFileConstants.JDK17,
TokenNameRestrictedIdentifiersealed,
Goal.RestrictedIdentifierSealedGoal);
return disambiguatesRestrictedIdentifierWithLookAhead(TokenNameRestrictedIdentifiersealed);
} else
return TokenNameIdentifier;
case 8 :
Expand Down Expand Up @@ -4525,7 +4519,6 @@ public static boolean isKeyword(int token) {
case TerminalTokens.TokenNameinstanceof:
case TerminalTokens.TokenNamelong:
case TerminalTokens.TokenNamenew:
case TerminalTokens.TokenNamenon_sealed:
case TerminalTokens.TokenNamenull:
case TerminalTokens.TokenNamenative:
case TerminalTokens.TokenNamepublic:
Expand Down Expand Up @@ -4554,6 +4547,7 @@ public static boolean isKeyword(int token) {
case TerminalTokens.TokenNameRestrictedIdentifiersealed:
case TerminalTokens.TokenNameRestrictedIdentifierpermits:
case TerminalTokens.TokenNameRestrictedIdentifierWhen:
case TerminalTokens.TokenNamenon_sealed:
// making explicit - not a (restricted) keyword but restricted identifier.
//$FALL-THROUGH$
default:
Expand Down Expand Up @@ -4621,8 +4615,8 @@ private static class Goal {
static int BlockStatementoptRule = 0;
static int YieldStatementRule = 0;
static int SwitchLabelCaseLhsRule = 0;
static int[] RestrictedIdentifierSealedRule;
static int RestrictedIdentifierPermitsRule;
static int[] ModifiersoptRules;
static int PermittedTypesRule;
static int[] PatternRules;

static Goal LambdaParameterListGoal;
Expand All @@ -4632,18 +4626,18 @@ private static class Goal {
static Goal BlockStatementoptGoal;
static Goal YieldStatementGoal;
static Goal SwitchLabelCaseLhsGoal;
static Goal RestrictedIdentifierSealedGoal;
static Goal RestrictedIdentifierPermitsGoal;
static Goal SealedModifierGoal;
static Goal PermittedTypesGoal;
static Goal PatternGoal;

static int[] RestrictedIdentifierSealedFollow = { TokenNameclass, TokenNameinterface,
static int[] SealedModifierFollow = { TokenNameclass, TokenNameinterface,
TokenNameenum, TokenNameRestrictedIdentifierrecord };// Note: enum/record allowed as error flagging rules.
static int[] RestrictedIdentifierPermitsFollow = { TokenNameLBRACE };
static int[] PermittedTypesFollow = { TokenNameLBRACE };
static int[] PatternCaseLabelFollow = {TokenNameCOLON, TokenNameARROW, TokenNameCOMMA, TokenNameBeginCaseExpr, TokenNameRestrictedIdentifierWhen};

static {

List<Integer> ridSealed = new ArrayList<>(2);
List<Integer> modifiersOptStates = new ArrayList<>(2);
List<Integer> patternStates = new ArrayList<>();
for (int i = 1; i <= ParserBasicInformation.NUM_RULES; i++) { // 0 == $acc
// TODO: Change to switch
Expand All @@ -4666,10 +4660,10 @@ private static class Goal {
YieldStatementRule = i;
else
if ("Modifiersopt".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
ridSealed.add(i);
modifiersOptStates.add(i);
else
if ("PermittedSubtypes".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
RestrictedIdentifierPermitsRule = i;
if ("PermittedTypes".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
PermittedTypesRule = i;
else
if ("SwitchLabelCaseLhs".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
SwitchLabelCaseLhsRule = i;
Expand All @@ -4683,7 +4677,7 @@ private static class Goal {
if ("RecordPattern".equals(Parser.name[Parser.non_terminal_index[Parser.lhs[i]]])) //$NON-NLS-1$
patternStates.add(i);
}
RestrictedIdentifierSealedRule = ridSealed.stream().mapToInt(Integer :: intValue).toArray(); // overkill but future-proof
ModifiersoptRules = modifiersOptStates.stream().mapToInt(Integer :: intValue).toArray(); // overkill but future-proof
PatternRules = patternStates.stream().mapToInt(Integer :: intValue).toArray();

LambdaParameterListGoal = new Goal(TokenNameARROW, new int[] { TokenNameARROW }, LambdaParameterListRule);
Expand All @@ -4693,8 +4687,8 @@ private static class Goal {
BlockStatementoptGoal = new Goal(TokenNameLBRACE, new int [0], BlockStatementoptRule);
YieldStatementGoal = new Goal(TokenNameARROW, new int [0], YieldStatementRule);
SwitchLabelCaseLhsGoal = new Goal(TokenNameARROW, new int [0], SwitchLabelCaseLhsRule);
RestrictedIdentifierSealedGoal = new Goal(TokenNameRestrictedIdentifiersealed, RestrictedIdentifierSealedFollow, RestrictedIdentifierSealedRule);
RestrictedIdentifierPermitsGoal = new Goal(TokenNameRestrictedIdentifierpermits, RestrictedIdentifierPermitsFollow, RestrictedIdentifierPermitsRule);
SealedModifierGoal = new Goal(TokenNameRestrictedIdentifiersealed, SealedModifierFollow, ModifiersoptRules);
PermittedTypesGoal = new Goal(TokenNameRestrictedIdentifierpermits, PermittedTypesFollow, PermittedTypesRule);
PatternGoal = new Goal(TokenNameBeginCaseElement, PatternCaseLabelFollow, PatternRules);
}

Expand Down Expand Up @@ -5227,14 +5221,34 @@ int disambiguatedRestrictedKeyword(int restrictedKeywordToken) {
}
return token;
}
int disambiguatesRestrictedIdentifierWithLookAhead(Predicate<Integer> checkPrecondition, int restrictedIdentifierToken, Goal goal) {
if (checkPrecondition.test(restrictedIdentifierToken)) {
VanguardParser vp = getNewVanguardParser();
VanguardScanner vs = (VanguardScanner) vp.scanner;
vs.resetTo(this.currentPosition, this.eofPosition - 1);
if (vp.parse(goal) == VanguardParser.SUCCESS)
return restrictedIdentifierToken;
// TODO: Centralize all non-module contextual keyword recognition here. ATM, we handle sealed type related tokens.
int disambiguatesRestrictedIdentifierWithLookAhead(int restrictedIdentifierToken) {
if (isInModuleDeclaration())
return TokenNameIdentifier;

Goal goal;
switch (restrictedIdentifierToken) {
case TokenNameRestrictedIdentifiersealed:
case TokenNamenon_sealed:
if (this.sourceLevel < ClassFileConstants.JDK17)
return TokenNameIdentifier;
goal = Goal.SealedModifierGoal;
break;
case TokenNameRestrictedIdentifierpermits:
if (this.sourceLevel < ClassFileConstants.JDK17)
return TokenNameIdentifier;
goal = Goal.PermittedTypesGoal;
break;
default:
throw new UnsupportedOperationException("Unhandled contextual keyword"); //$NON-NLS-1$
}

VanguardParser vp = getNewVanguardParser();
VanguardScanner vs = (VanguardScanner) vp.scanner;
vs.resetTo(this.currentPosition, this.eofPosition - 1);
if (vp.parse(goal) == VanguardParser.SUCCESS)
return restrictedIdentifierToken;

return TokenNameIdentifier;
}

Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ PackageDeclarationName=PackageDeclarationName
ParenthesizedCastNameAndBounds=ParenthesizedCastNameAndBounds
ParenthesizedLambdaParameterList=ParenthesizedLambdaParameterList
Pattern=Pattern
PermittedSubtypes=PermittedSubtypes
PermittedTypesopt=PermittedTypes
PermittedTypes=PermittedTypes
PermittedTypesopt=PermittedTypesopt
PostDecrementExpression=PostDecrementExpression
PostIncrementExpression=PostIncrementExpression
PostfixExpression=Expression
Expand Down

0 comments on commit 73a5099

Please sign in to comment.