Files
rose-ash/lib/erlang/parser-module.sx
giles 99753580b4 Recover agent-loop progress: lua/prolog/forth/erlang/haskell phases 1-2
Salvaged from worktree-agent-* branches killed during sx-tree MCP outage:
- lua: tokenizer + parser + phase-2 transpile (~157 tests)
- prolog: tokenizer + parser + unification (72 tests, plan update lost to WIP)
- forth: phase-1 reader/interpreter + phase-2 colon/VARIABLE (134 tests)
- erlang: tokenizer + parser (114 tests)
- haskell: tokenizer + parse tests (43 tests)

Cherry-picked file contents only, not branch history, to avoid pulling in
unrelated ocaml-vm merge commits that were in those branches' bases.
2026-04-24 16:03:00 +00:00

114 lines
3.0 KiB
Plaintext

;; Erlang module parser — reads top-level forms and builds a module AST.
;;
;; Depends on parser-core.sx, parser.sx, parser-expr.sx.
(define
er-parse-module
(fn
(src)
(let
((st (er-state-make (er-tokenize src)))
(mod-ref (list nil))
(attrs (list))
(functions (list)))
(er-parse-module-loop st mod-ref attrs functions)
{:functions functions :type "module" :attrs attrs :name (nth mod-ref 0)})))
(define
er-parse-module-loop
(fn
(st mod-ref attrs functions)
(when
(not (er-at-eof? st))
(er-parse-top-form st mod-ref attrs functions)
(er-parse-module-loop st mod-ref attrs functions))))
(define
er-parse-top-form
(fn
(st mod-ref attrs functions)
(cond
(er-is? st "op" "-")
(do
(er-advance! st)
(let
((attr-name (er-cur-value st)))
(er-advance! st)
(let
((args (er-parse-attr-args st)))
(er-expect! st "punct" ".")
(cond
(= attr-name "module")
(set-nth! mod-ref 0 (get (nth args 0) :value))
:else (append! attrs {:args args :name attr-name})))))
(= (er-cur-type st) "atom")
(append! functions (er-parse-function st))
:else (error
(str
"Erlang parse (top): unexpected "
(er-cur-type st)
" '"
(er-cur-value st)
"' at pos "
(get (er-cur st) :pos))))))
(define
er-parse-attr-args
(fn
(st)
(er-expect! st "punct" "(")
(if
(er-is? st "punct" ")")
(do (er-advance! st) (list))
(let
((args (list (er-parse-attr-arg st))))
(er-parse-attr-args-tail st args)))))
(define
er-parse-attr-args-tail
(fn
(st args)
(cond
(er-is? st "punct" ",")
(do
(er-advance! st)
(append! args (er-parse-attr-arg st))
(er-parse-attr-args-tail st args))
(er-is? st "punct" ")")
(do (er-advance! st) args)
:else (error (str "Erlang parse attr: got '" (er-cur-value st) "'")))))
;; Attribute args often contain `Name/Arity` pairs — parse as a
;; general expression so the caller can interpret the shape.
(define er-parse-attr-arg (fn (st) (er-parse-expr-prec st 0)))
(define
er-parse-function
(fn
(st)
(let
((name (er-cur-value st)))
(er-advance! st)
(let
((clauses (list (er-parse-fun-clause st name))))
(er-parse-function-tail st name clauses)
(er-expect! st "punct" ".")
(let ((arity (len (get (nth clauses 0) :patterns)))) {:arity arity :clauses clauses :type "function" :name name})))))
(define
er-parse-function-tail
(fn
(st name clauses)
(when
(er-is? st "punct" ";")
(let
((save (get st :idx)))
(er-advance! st)
(if
(and (= (er-cur-type st) "atom") (= (er-cur-value st) name))
(do
(er-advance! st)
(append! clauses (er-parse-fun-clause st name))
(er-parse-function-tail st name clauses))
(dict-set! st :idx save))))))