Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions src/main/java/org/perlonjava/runtime/regex/JoniRegexPattern.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ private static CharacterPropertyResolver.Result resolveCharacterProperty(
JoniRegexPattern(String perlPattern, RegexFlags flags, int trustedCalloutCount,
boolean forceAsciiClasses, boolean byteMode,
boolean byteBackedPattern) {
KeepSyntax keepSyntax = analyzeKeepSyntax(perlPattern, flags.isExtended());
if (keepSyntax.inLookaround()) {
PerlSyntaxFeatures syntaxFeatures = analyzePerlSyntax(perlPattern, flags.isExtended());
if (syntaxFeatures.keepInLookaround()) {
throw new PerlCompilerException("\\K not permitted in lookahead/lookbehind in regex");
}
this.flags = flags;
Expand Down Expand Up @@ -342,7 +342,10 @@ static boolean requiresJoniBackend(String pattern, RegexFlags flags) {
// implementation passes its combined imported-corpus gate. Explicit
// Joni mode still exercises the native implementation directly.
boolean branchResetCallUsesJava = pattern.contains("(?|") && hasSubroutineCall;
return analyzeKeepSyntax(pattern, flags != null && flags.isExtended()).present()
PerlSyntaxFeatures syntaxFeatures = analyzePerlSyntax(
pattern, flags != null && flags.isExtended());
return syntaxFeatures.keepPresent()
|| syntaxFeatures.conditionalPresent()
|| pattern.contains("(?{=CALL:")
|| pattern.contains("(?{=DYNAMIC:")
|| pattern.contains("(*ACCEPT)")
Expand All @@ -352,24 +355,22 @@ static boolean requiresJoniBackend(String pattern, RegexFlags flags) {
|| pattern.contains("(*COMMIT")
|| pattern.contains("(*MARK")
|| pattern.contains("(*:")
|| pattern.contains("(?(DEFINE)")
|| pattern.contains("(?(?{=CALL:")
|| pattern.contains("(?(R")
|| pattern.contains("(?(<")
|| pattern.contains("(?('")
|| (hasSubroutineCall && !branchResetCallUsesJava);
}

private record KeepSyntax(boolean present, boolean inLookaround) {}
private record PerlSyntaxFeatures(boolean keepPresent,
boolean keepInLookaround,
boolean conditionalPresent) {}

private static KeepSyntax analyzeKeepSyntax(String pattern, boolean extended) {
private static PerlSyntaxFeatures analyzePerlSyntax(String pattern, boolean extended) {
boolean quoted = false;
boolean inClass = false;
boolean classStart = false;
int extendedClassDepth = 0;
int lookaroundDepth = 0;
java.util.ArrayDeque<Boolean> groups = new java.util.ArrayDeque<>();
boolean present = false;
boolean keepPresent = false;
boolean conditionalPresent = false;

for (int i = 0; i < pattern.length(); i++) {
char ch = pattern.charAt(i);
Expand Down Expand Up @@ -431,8 +432,10 @@ private static KeepSyntax analyzeKeepSyntax(String pattern, boolean extended) {
if (escaped == 'Q') {
quoted = true;
} else if (escaped == 'K') {
present = true;
if (lookaroundDepth > 0) return new KeepSyntax(true, true);
keepPresent = true;
if (lookaroundDepth > 0) {
return new PerlSyntaxFeatures(true, true, conditionalPresent);
}
}
continue;
}
Expand All @@ -443,6 +446,7 @@ private static KeepSyntax analyzeKeepSyntax(String pattern, boolean extended) {
i = close;
continue;
}
if (pattern.startsWith("(?(", i)) conditionalPresent = true;
boolean lookaround = pattern.startsWith("(?=", i)
|| pattern.startsWith("(?!", i)
|| pattern.startsWith("(?<=", i)
Expand All @@ -453,7 +457,7 @@ private static KeepSyntax analyzeKeepSyntax(String pattern, boolean extended) {
if (groups.pop()) lookaroundDepth--;
}
}
return new KeepSyntax(present, false);
return new PerlSyntaxFeatures(keepPresent, false, conditionalPresent);
}

private static boolean hasControlVerbState(String pattern) {
Expand Down
Loading