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
21 changes: 20 additions & 1 deletion src/main/java/org/perlonjava/frontend/parser/FileHandle.java
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ public static Node parseBarewordHandle(Parser parser, String name) {

// Check if this is a known file handle in the global I/O table
// This helps distinguish between file handles and other barewords
if (GlobalVariable.existsGlobalIO(name) || isStandardFilehandle(name)) {
if (GlobalVariable.existsGlobalIO(name) || isStandardFilehandle(name)
|| isAllDigitGlobName(name)) {
// Create a GLOB reference for the file handle, like `\*FH`
return new OperatorNode("\\",
new OperatorNode("*",
Expand All @@ -280,6 +281,24 @@ public static Node parseBarewordHandle(Parser parser, String name) {
return null;
}

/**
* Perl allows numeric typeglob names such as {@code open 0; print <0>}, where filehandle
* {@code 0} shares the {@code *0} stash entry with {@code $0} (program name).
*/
private static boolean isAllDigitGlobName(String normalizedName) {
int idx = normalizedName.lastIndexOf("::");
String base = idx >= 0 ? normalizedName.substring(idx + 2) : normalizedName;
if (base.isEmpty()) {
return false;
}
for (int i = 0; i < base.length(); i++) {
if (!Character.isDigit(base.charAt(i))) {
return false;
}
}
return true;
}

/**
* Checks if a normalized name represents a standard filehandle.
*
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/org/perlonjava/frontend/parser/OperatorParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ static Node parseDiamondOperator(Parser parser, LexerToken token) {
return diamond;
}

// <0>, <1>, … — numeric filehandles (e.g. Acme::Buffy "open 0" reads $0)
if (operand.type == NUMBER && tokenText.matches("[0-9]+")
&& parser.tokens.get(parser.tokenIndex + 1).text.equals(">")) {
parser.tokenIndex++; // consume NUMBER
TokenUtils.consume(parser); // consume '>'
String digitName = operand.text;
GlobalVariable.getGlobalIO(FileHandle.normalizeBarewordHandle(parser, digitName));
Node globRef = FileHandle.parseBarewordHandle(parser, digitName);
if (globRef != null) {
BinaryOperatorNode readlineNode = new BinaryOperatorNode("readline",
globRef,
new ListNode(parser.tokenIndex), currentTokenIndex);
readlineNode.setAnnotation("handleName", digitName);
return readlineNode;
}
parser.tokenIndex = currentTokenIndex;
}

// Check if the token looks like a Bareword file handle
if (operand.type == IDENTIFIER) {
Node fileHandle = FileHandle.parseFileHandle(parser);
Expand Down
Loading