Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -1480,8 +1480,9 @@ private boolean isHexDigit(String chr) {
*/
void handleUnicodeNameEscape() {
if (!"{".equals(TokenUtils.peekChar(parser))) {
// Not a Unicode name escape, treat as literal
appendToCurrentSegment("N");
// In a regex, plain \N is Perl's non-newline atom. Keep the escape
// intact for the regex backend; quoted strings still treat it as N.
appendToCurrentSegment(isRegex ? "\\N" : "N");
return;
}

Expand All @@ -1498,6 +1499,12 @@ void handleUnicodeNameEscape() {
if ("}".equals(chr)) {
TokenUtils.consumeChar(parser); // consume '}'
var name = nameBuilder.toString();
if (isRegex && isPlainNonNewlineInterval(name)) {
// A brace immediately following plain \N can be its quantifier,
// not a named character. Leave both pieces for the regex lexer.
appendToCurrentSegment("\\N{" + name + "}");
return;
}
NamedCharacterExpansion.SourceMode sourceMode =
ctx.compilerOptions.isByteStringSource
|| (!ctx.symbolTable.isStrictOptionEnabled(HINT_UTF8)
Expand All @@ -1518,7 +1525,7 @@ void handleUnicodeNameEscape() {
throwNamedSequenceExtendedClassDiagnostic(expansion.sequence());
}
if (!expansion.resolved()) {
parser.throwError(expansion.diagnostic());
throwNamedCharacterDiagnostic(expansion.diagnostic());
}
}
appendToCurrentSegment("\\N{" + name + "}");
Expand All @@ -1528,18 +1535,26 @@ void handleUnicodeNameEscape() {
NamedCharacterExpansion.resolve(name, sourceMode);
if (expansion.resolved()) {
appendToCurrentSegment(expansion.sequence());
} else if (expansion.status() == NamedCharacterExpansion.Status.INVALID) {
parser.throwError(expansion.diagnostic());
} else {
// Preserve the historical literal fallback when no standard
// name or lexical translator resolves this escape.
appendToCurrentSegment("N{" + name + "}");
throwNamedCharacterDiagnostic(expansion.diagnostic());
}
} else {
throwMissingNamedCharacterBraceDiagnostic();
}
}

private boolean isPlainNonNewlineInterval(String contents) {
return contents.matches("(?:[0-9]+(?:,[0-9]*)?|,[0-9]+)");
}

private void throwNamedCharacterDiagnostic(String diagnostic) {
int errorIndex = this.tokenIndex;
var location = ctx.errorUtil.getSourceLocationAccurate(errorIndex);
throw new PerlParserException(diagnostic
+ " at " + location.fileName() + " line " + location.lineNumber()
+ ", within " + (isRegex ? "pattern" : "string") + "\n");
}

private void throwMissingNamedCharacterBraceDiagnostic() {
var location = ctx.errorUtil.getSourceLocationAccurate(parser.tokenIndex);
String message = isRegex
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ public static NamedCharacterExpansion resolve(String name, SourceMode inputMode)
*/
public static NamedCharacterExpansion resolve(
String name, RuntimeScalar translator, SourceMode inputMode) {
if (name != null && name.matches("(?i)U\\+[0-9A-F]+")) {
return resolveStandard(name);
if (name != null && name.regionMatches(true, 0, "U+", 0, 2)) {
if (name.matches("(?i)U\\+[0-9A-F]+")) {
return resolveStandard(name);
}
return new NamedCharacterExpansion(
"", SourceMode.UNICODE, true, Status.INVALID,
"Invalid hexadecimal number in \\N{U+...}");
}
RuntimeScalar callable = unwrapCallable(translator);
if (callable != null) {
Expand Down
118 changes: 0 additions & 118 deletions src/main/java/org/perlonjava/runtime/regex/BranchResetCaptureMap.java

This file was deleted.

42 changes: 4 additions & 38 deletions src/main/java/org/perlonjava/runtime/regex/JavaRegexMatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,8 @@

final class JavaRegexMatcher implements RegexMatcher {
private final Matcher matcher;
private final int[] javaToPerlGroup;
private final int perlGroupCount;

JavaRegexMatcher(Matcher matcher) {
this(matcher, null);
}

JavaRegexMatcher(Matcher matcher, int[] javaToPerlGroup) {
this.matcher = matcher;
this.javaToPerlGroup = javaToPerlGroup != null
&& javaToPerlGroup.length == matcher.groupCount()
? javaToPerlGroup
: null;
int maximum = 0;
if (this.javaToPerlGroup != null) {
for (int group : this.javaToPerlGroup) maximum = Math.max(maximum, group);
}
this.perlGroupCount = this.javaToPerlGroup == null ? matcher.groupCount() : maximum;
}

Matcher unwrap() {
Expand All @@ -35,33 +19,15 @@ Matcher unwrap() {
@Override public void useTransparentBounds(boolean enabled) { matcher.useTransparentBounds(enabled); }
@Override public int start() { return matcher.start(); }
@Override public int end() { return matcher.end(); }
@Override public int start(int index) { return mappedOffset(index, true); }
@Override public int end(int index) { return mappedOffset(index, false); }
@Override public int start(int index) { return matcher.start(index); }
@Override public int end(int index) { return matcher.end(index); }
@Override public int start(String name) { return matcher.start(name); }
@Override public int end(String name) { return matcher.end(name); }
@Override public String group(int index) {
if (javaToPerlGroup == null || index == 0) return matcher.group(index);
for (int javaGroup = 1; javaGroup <= javaToPerlGroup.length; javaGroup++) {
if (javaToPerlGroup[javaGroup - 1] == index && matcher.start(javaGroup) >= 0) {
return matcher.group(javaGroup);
}
}
return null;
return matcher.group(index);
}
@Override public String group(String name) { return matcher.group(name); }
@Override public int groupCount() { return perlGroupCount; }
@Override public int groupCount() { return matcher.groupCount(); }
@Override public Map<String, Integer> namedGroups() { return matcher.pattern().namedGroups(); }
@Override public String patternDescription() { return matcher.pattern().pattern(); }

private int mappedOffset(int index, boolean start) {
if (javaToPerlGroup == null || index == 0) {
return start ? matcher.start(index) : matcher.end(index);
}
for (int javaGroup = 1; javaGroup <= javaToPerlGroup.length; javaGroup++) {
if (javaToPerlGroup[javaGroup - 1] == index && matcher.start(javaGroup) >= 0) {
return start ? matcher.start(javaGroup) : matcher.end(javaGroup);
}
}
return -1;
}
}
Loading
Loading