# deft/parse-forms
Parse arbitrary Deft source into `%Sexpr{}` form trees without evaluating
it. Unlike `deft/parse`, which accepts only data literals, this runs the
full kernel parser — calls, `def`s, control flow, decorators, and map
literals all come back as structured forms with source positions, so
tooling (importers, graph builders, syntax tools) can inspect code
without invoking the compiler.
## Syntax
[deft/parse-forms $source]
## Parameters
- `$source` — Deft source text (string). Multiple top-level forms are
all returned.
## Returns
`%{ :forms @{%Sexpr{} ...} :errors @{%{ :line :col :message } ...} }`.
Every form is a `%Sexpr{}` tagged map carrying:
- `:tag` — one of `:symbol`, `:keyword`, `:string`, `:raw-string`,
`:number`, `:bool`, `:nil`, `:call`, `:list`, `:map`, `:value`
- `:line` / `:col` — 1-based position of the form's first token
- payload — `:value` (scalars), `:items` (`:call` / `:list`, a vector of
child forms), or `:pairs` (`:map`, a vector of `[key value]` vectors);
`:nil` and `:value` carry no payload
`:call` is a bracket `[...]` form; a non-bracket list — an infix group
`(...)` or a `{ ... }` block body — is `:list`. The parser lowers some
syntax before returning it: a `def` becomes
`(__defproc name params body)`, typed/default/rest params become
`(typed-param ...)` / `(default-typed-param ...)` / `(rest-param ...)`,
a map literal becomes `(__make-map k v ...)`, and a decorator becomes
`(decorator name value)`.
Malformed source does not throw: the parser recovers as far as it can,
returns the forms it built, and lists diagnostics in `:errors`. A lex
or fatal parse failure returns `%Err{:message}` instead.
## Examples
set p [deft/parse-forms "set x [len \$xs]"] set stmt [first $p~forms] $stmt~tag # → :list [get [nth $stmt~items 2] :tag] # → :call (the [len $xs]) # A def lowers to (__defproc name params body) set d [first [get [deft/parse-forms "def f {|a^number| \$a}"] :forms]] [get [first $d~items] :value] # → "__defproc" # Malformed source: forms plus diagnostics, never an exception set r [deft/parse-forms "set y (1 +"] [get [first $r~errors] :message] # → parser diagnostic text
## See Also
`deft/parse`, `deft/stringify`, `deft/syntax-highlight`, `eval`