Skip to content

Fix JSX elements closed directly before |] and } - #17

Merged
andreypopp merged 3 commits into
mainfrom
fix/jsx-close-in-array-and-record
Sep 16, 2026
Merged

andreypopp merged 3 commits into
mainfrom
fix/jsx-close-in-array-and-record

Conversation

@andreypopp

Copy link
Copy Markdown
Member

Port of ocaml-mlx/mlx#46 to the formatter's two vendored parsers, fixing:

let _ = [|<div>aa</div>|]     (* >|] lexed as the >| operator + ] *)
let _ = {x = <div>a</div>}    (* >} lexed as GREATERRBRACE *)

Same mechanics as the mlx PR: a >|] lexer rule gives the > back so |] lexes as BARRBRACKET; >} is stolen the same way, with the object-override productions closing via GREATER RBRACE instead of the single GREATERRBRACE token ({< x = 2 >} keeps working in both spacings). Menhir reports zero conflicts before and after in both grammars (--strict --explain); the dead GREATERRBRACE token joins the --unused-token lists since this fork builds menhir with --strict.

Additional formatter fix the mlx repo didn't need: Pexp_override printing now keeps parentheses around a bare > comparison used as a field value — dropping them (previous behavior) produces output that no longer reparses under the two-token close. Testing here also showed the known limitation from ocaml-mlx/mlx#46 is broader than the PR states: an unparenthesized a > b in any override field position (not just the last) needs parens now, in both repos.

Tests: array/list/record/with-update JSX closes, override both spacings, paren-preserving comparison cases, >| operator sanity, all idempotent; the full ocamlformat suite passes with no changes to pre-existing {< ... >} tests. CHANGES.md entry included.

🤖 Generated with Claude Code

Port of ocaml-mlx/mlx#46 to both vendored parsers: a dedicated `>|]`
lexer rule backtracks to give the `>` back so `|]` lexes as
BARRBRACKET, and `>}` is stolen the same way with the object-override
grammar compensating by closing with GREATER RBRACE.

Also fix Pexp_override printing to keep parentheses around a bare `>`
comparison used as a field value (any field, not just the last one):
dropping them produced output that fails the reparse self-check, since
an unparenthesized `a > b` in an override field list is ambiguous with
the closing `>` under the new two-token close.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`(x : <m : int>)` failed to parse because `<m` lexes as the JSX
element-open token even in type position, where JSX can never occur.
Both vendored grammars now accept the fused token as `<` plus the
first method label: field/field_semi are parameterized over the
label symbol, and object_type gains a meth_list_jsx alternative fed
by an inline jsx_first_label rule. Lexers untouched; spaced object
types, `< .. >`, and expression JSX are covered by regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andreypopp

Copy link
Copy Markdown
Member Author

Second commit: same object-type fix as ocaml-mlx/mlx#46 — (x : <m : int>) parses now; both vendored grammars accept the fused <m token as < + first method label. Formatter output unchanged (always prints spaced object types).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@andreypopp
andreypopp merged commit 4c70c1d into main Sep 16, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants