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.
This commit is contained in:
111
lib/erlang/parser.sx
Normal file
111
lib/erlang/parser.sx
Normal file
@@ -0,0 +1,111 @@
|
||||
;; Erlang parser — turns a token list into an AST.
|
||||
;;
|
||||
;; Shared state lives in the surrounding `let` of `er-parse-*`.
|
||||
;; All helpers use recursion (no `while` in SX).
|
||||
;;
|
||||
;; AST node shapes:
|
||||
;; {:type "atom" :value "foo"}
|
||||
;; {:type "integer" :value "42"} ; value kept as string
|
||||
;; {:type "float" :value "3.14"}
|
||||
;; {:type "string" :value "hi"}
|
||||
;; {:type "var" :name "X"} ; "_" is wildcard
|
||||
;; {:type "nil"}
|
||||
;; {:type "tuple" :elements [...]}
|
||||
;; {:type "cons" :head E :tail E}
|
||||
;; {:type "call" :fun E :args [...]}
|
||||
;; {:type "remote" :mod E :fun E}
|
||||
;; {:type "op" :op OP :args [L R]}
|
||||
;; {:type "unop" :op OP :arg E}
|
||||
;; {:type "match" :lhs P :rhs E}
|
||||
;; {:type "send" :to E :msg E}
|
||||
;; {:type "if" :clauses [{:guards [...] :body [...]} ...]}
|
||||
;; {:type "case" :expr E :clauses [{:pattern P :guards [...] :body [...]} ...]}
|
||||
;; {:type "receive" :clauses [...] :after-ms E-or-nil :after-body [...]}
|
||||
;; {:type "fun" :clauses [...]}
|
||||
;; {:type "block" :exprs [...]}
|
||||
;; {:type "try" :exprs [...] :of-clauses [...] :catch-clauses [...] :after [...]}
|
||||
;; Top-level: {:type "module" :name A :attrs [{:name A :args [...]} ...] :functions [...]}
|
||||
;; {:type "function" :name A :arity N :clauses [{:name :patterns :guards :body}]}
|
||||
|
||||
(define
|
||||
er-is-binop?
|
||||
(fn
|
||||
(tok prec)
|
||||
(let
|
||||
((ty (get tok :type)) (v (get tok :value)))
|
||||
(cond
|
||||
(= prec 0)
|
||||
(and (= ty "op") (= v "="))
|
||||
(= prec 1)
|
||||
(and (= ty "op") (= v "!"))
|
||||
(= prec 2)
|
||||
(or
|
||||
(and (= ty "keyword") (= v "orelse"))
|
||||
(and (= ty "keyword") (= v "or"))
|
||||
(and (= ty "keyword") (= v "xor")))
|
||||
(= prec 3)
|
||||
(or
|
||||
(and (= ty "keyword") (= v "andalso"))
|
||||
(and (= ty "keyword") (= v "and")))
|
||||
(= prec 4)
|
||||
(and
|
||||
(= ty "op")
|
||||
(or
|
||||
(= v "==")
|
||||
(= v "/=")
|
||||
(= v "=:=")
|
||||
(= v "=/=")
|
||||
(= v "<")
|
||||
(= v ">")
|
||||
(= v "=<")
|
||||
(= v ">=")))
|
||||
(= prec 5)
|
||||
(and (= ty "op") (or (= v "++") (= v "--")))
|
||||
(= prec 6)
|
||||
(and (= ty "op") (or (= v "+") (= v "-")))
|
||||
(= prec 7)
|
||||
(or
|
||||
(and (= ty "op") (or (= v "*") (= v "/")))
|
||||
(and
|
||||
(= ty "keyword")
|
||||
(or
|
||||
(= v "div")
|
||||
(= v "rem")
|
||||
(= v "band")
|
||||
(= v "bor")
|
||||
(= v "bxor")
|
||||
(= v "bsl")
|
||||
(= v "bsr"))))
|
||||
:else false))))
|
||||
|
||||
(define
|
||||
er-any-binop?
|
||||
(fn
|
||||
(tok min-prec)
|
||||
(or
|
||||
(and (>= 0 min-prec) (er-is-binop? tok 0))
|
||||
(and (>= 1 min-prec) (er-is-binop? tok 1))
|
||||
(and (>= 2 min-prec) (er-is-binop? tok 2))
|
||||
(and (>= 3 min-prec) (er-is-binop? tok 3))
|
||||
(and (>= 4 min-prec) (er-is-binop? tok 4))
|
||||
(and (>= 5 min-prec) (er-is-binop? tok 5))
|
||||
(and (>= 6 min-prec) (er-is-binop? tok 6))
|
||||
(and (>= 7 min-prec) (er-is-binop? tok 7)))))
|
||||
|
||||
(define
|
||||
er-slice-list
|
||||
(fn
|
||||
(xs from)
|
||||
(if
|
||||
(>= from (len xs))
|
||||
(list)
|
||||
(let
|
||||
((out (list)))
|
||||
(for-each
|
||||
(fn (i) (append! out (nth xs i)))
|
||||
(range from (len xs)))
|
||||
out))))
|
||||
|
||||
(define
|
||||
er-build-cons
|
||||
(fn (elems tail) (if (= (len elems) 0) tail {:head (nth elems 0) :tail (er-build-cons (er-slice-list elems 1) tail) :type "cons"})))
|
||||
Reference in New Issue
Block a user