erlang: binary pattern matching <<...>> (+21 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-25 06:54:58 +00:00
parent 193b0c04be
commit ce8ff8b738
6 changed files with 334 additions and 7 deletions

View File

@@ -237,6 +237,8 @@
(er-parse-fun-expr st)
(er-is? st "keyword" "try")
(er-parse-try st)
(er-is? st "punct" "<<")
(er-parse-binary st)
:else (error
(str
"Erlang parse: unexpected "
@@ -576,3 +578,63 @@
((guards (if (er-is? st "keyword" "when") (do (er-advance! st) (er-parse-guards st)) (list))))
(er-expect! st "punct" "->")
(let ((body (er-parse-body st))) {:pattern pat :body body :class klass :guards guards}))))))
;; ── binary literals / patterns ────────────────────────────────
;; `<< [Seg {, Seg}] >>` where Seg = Value [: Size] [/ Spec]. Size is
;; a literal integer (multiple of 8 supported); Spec is `integer`
;; (default) or `binary` (rest-of-binary tail). Sufficient for the
;; common `<<A:8, B:16, Rest/binary>>` patterns.
(define
er-parse-binary
(fn
(st)
(er-expect! st "punct" "<<")
(cond
(er-is? st "punct" ">>")
(do (er-advance! st) {:segments (list) :type "binary"})
:else (let
((segs (list (er-parse-binary-segment st))))
(er-parse-binary-tail st segs)))))
(define
er-parse-binary-tail
(fn
(st segs)
(cond
(er-is? st "punct" ",")
(do
(er-advance! st)
(append! segs (er-parse-binary-segment st))
(er-parse-binary-tail st segs))
(er-is? st "punct" ">>")
(do (er-advance! st) {:segments segs :type "binary"})
:else (error
(str
"Erlang parse: expected ',' or '>>' in binary, got '"
(er-cur-value st)
"'")))))
(define
er-parse-binary-segment
(fn
(st)
;; Use `er-parse-primary` for the value so a leading `:` falls
;; through to the segment's size suffix instead of being eaten
;; by `er-parse-postfix-loop` as a `Mod:Fun` remote call.
(let
((v (er-parse-primary st)))
(let
((size (cond
(er-is? st "punct" ":")
(do (er-advance! st) (er-parse-primary st))
:else nil))
(spec (cond
(er-is? st "op" "/")
(do
(er-advance! st)
(let
((tok (er-cur st)))
(er-advance! st)
(get tok :value)))
:else "integer")))
{:size size :spec spec :value v}))))