erlang: binary pattern matching <<...>> (+21 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -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}))))
|
||||
|
||||
Reference in New Issue
Block a user