Skip to content

fix: parse hashref after any operator as Constructor (GH #34) - #433

Draft
toddr-bot wants to merge 2 commits into
masterfrom
koan.toddr.bot/fix-issue-34
Draft

fix: parse hashref after any operator as Constructor (GH #34)#433
toddr-bot wants to merge 2 commits into
masterfrom
koan.toddr.bot/fix-issue-34

Conversation

@toddr-bot

@toddr-bot toddr-bot commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

After any operator (e.g. or, and, -, ==, +=, ..), { } can only be an anonymous hashref (Constructor), never a code block. Previously PPI only recognized a handful of operators in %CURLY_CLASSES; all others fell through to a catch-all that returned Block.

Added a type-based check in _curly(): if the last significant element before { is a PPI::Token::Operator (and -> was already handled as Subscript), return PPI::Structure::Constructor. This covers all current and future operators without maintaining an exhaustive list.

Fixes #34

Changes

  • Added operator type check in Lexer.pm _curly() method after the %CURLY_CLASSES lookup
  • Updated test expectations in ppi_token_unknown.t for hashctors after operators (Block → Constructor)
  • Removed the "hash constructors are currently mistaken for blocks" TODO
  • Added regression tests in 08_regression.t covering or, and, not, -, ==, ne, .., +=

Test plan

  • All 69 test files pass (53,113 tests)
  • Verified the exact issue example: 0 || {b => 1, a => 1}; parses as Constructor
  • Verified 35+ operators produce Constructor after the fix
  • Verified Block cases (map, grep, sort, sub, do, eval, if, while, for) are unaffected
  • Verified Subscript cases ($foo->{bar}, $foo{bar}, @foo{bar}) are unaffected
  • Verified Cast contexts (+ *{$args}) correctly remain Block

Generated by Kōan /fix


Quality Report

Changes: 3 files changed, 69 insertions(+), 35 deletions(-)

Code scan: clean

Tests: skipped

Branch hygiene: clean

Generated by Kōan post-mission quality pipeline

toddr-bot and others added 2 commits April 27, 2026 08:39
Operators like 'or', 'and', 'not', '-', '==', 'ne', '..', '+=' should
produce PPI::Structure::Constructor when followed by {}, not Block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
After any PPI::Token::Operator, a { } can only be a hash constructor
(anonymous hashref), never a code block. Previously only a handful of
operators were listed in %CURLY_CLASSES; all others fell through to the
catch-all that returned Block.

Add a type-based check: if the last significant element before { is a
PPI::Token::Operator (and -> was already handled as Subscript), return
PPI::Structure::Constructor. This covers all current and future operators
without maintaining an exhaustive list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

anon hashref after operator treated as code block

2 participants