ocaml: parser accepts if/match/let/fun as rhs of <- and :=
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s

Previously `a.(i) <- if c then x else y` failed with
"unexpected token keyword if" because parse-binop-rhs called
parse-prefix for the rhs, which doesn't accept if/match/let/fun.

Real OCaml allows full expressions on the rhs of <-/:=. Fix:
special-case prec-1 ops in parse-binop-rhs to call parse-expr-no-seq
instead of parse-prefix. The recursive parse-binop-rhs with
min-prec restored after picks up any further chained <- (since both
ops are right-associative with no higher-prec binops above them).

Manacher baseline updated to use bare `if` on rhs of <-,
removing the parens workaround from iter 235. 607/607 regressions
remain clean.
This commit is contained in:
2026-05-10 06:11:57 +00:00
parent cccef832d9
commit 4fdf6980da
3 changed files with 33 additions and 15 deletions

View File

@@ -13,7 +13,7 @@ let manacher s =
if i < !right then begin
let v = !right - i in
let pm = p.(mirror) in
p.(i) <- (if pm < v then pm else v)
p.(i) <- if pm < v then pm else v
end;
while i + p.(i) + 1 < m && i - p.(i) - 1 >= 0
&& t.(i + p.(i) + 1) = t.(i - p.(i) - 1) do

View File

@@ -741,16 +741,28 @@
(else
(begin
(advance-tok!)
(let
((rhs (parse-prefix))
(next-min
(if
(ocaml-binop-right? op)
prec
(+ prec 1))))
(begin
(set! rhs (parse-binop-rhs rhs next-min))
(parse-binop-rhs (list :op op lhs rhs) min-prec))))))))))))
;; For `<-` and `:=`, the rhs is at expression
;; level — accept `if/match/let/fun/...` keywords
;; on the right (real OCaml does). Otherwise,
;; fall back to the standard prefix-then-binop
;; chain.
(cond
((or (= op "<-") (= op ":="))
(let ((rhs (parse-expr-no-seq)))
(parse-binop-rhs
(list :op op lhs rhs) min-prec)))
(else
(let
((rhs (parse-prefix))
(next-min
(if
(ocaml-binop-right? op)
prec
(+ prec 1))))
(begin
(set! rhs (parse-binop-rhs rhs next-min))
(parse-binop-rhs
(list :op op lhs rhs) min-prec))))))))))))))
(define
parse-binary
(fn