Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,43 @@ in which Carp gets parsed into a structured `Form` AST. Built on
(match (Reader.parse "; greeting\n(defn hello [name] (println &name))")
(Result.Success forms)
(for [i 0 (Array.length &forms)]
(println &(Form.str (Box.peek (Array.unsafe-nth &forms i)))))
(IO.println &(Form.str (Located.form (Box.peek (Array.unsafe-nth &forms i))))))
(Result.Error e)
(IO.errorln &(Parser.format-error &e)))
```

`Reader.parse` returns `(Result (Array (Box Form)) ParseErr)`.
`Reader.parse` returns `(Result (Array (Box Located)) ParseErr)`.

## Located

Every node the parser emits — top-level and nested alike — is a `Located`,
not a bare `Form`:

```clojure
(deftype Located
[form Form
info Info ; position of the form's first byte
end Info]) ; position just past its last byte

(deftype Info
[pos Int ; byte offset
line Int
col Int])
```

`Located.form` unwraps it, so it is the accessor you reach for in almost any
use of this library:

```clojure
(let [l (Box.peek (Array.unsafe-nth &forms 0))]
(println* (Form.str (Located.form l))
" at line " @(Info.line (Located.info l))
", column " @(Info.col (Located.info l))))
```

`Located.str` is shorthand for `(Form.str (Located.form l))` when you do not
need the position. Nodes that reader macros synthesize rather than read from
source carry `Info.synthetic`, whose fields are all `0`.

## Form shape

Expand All @@ -36,10 +67,10 @@ in which Carp gets parsed into a structured `Form` AST. Built on
(Str [String])
(Pat [String]) ; #"..." pattern literal
(Sym [(Array String)]) ; ["Foo" "Bar" "baz"]
(Lst [(Array (Box Form))]) ; (...)
(Arr [(Array (Box Form))]) ; [...]
(StaticArr [(Array (Box Form))]) ; $[...]
(Dict [(Array (Box Form))]) ; {...}
(Lst [(Array (Box Located))]) ; (...)
(Arr [(Array (Box Located))]) ; [...]
(StaticArr [(Array (Box Located))]) ; $[...]
(Dict [(Array (Box Located))]) ; {...}
(Cmt [String])) ; ; line comment
```

Expand Down
9 changes: 5 additions & 4 deletions carp-reader.carp
Original file line number Diff line number Diff line change
Expand Up @@ -1025,12 +1025,13 @@ you need it.")
0))

(doc parse "parses a Carp source string into an array of top-level
`Form` forms. Comments are preserved as `Form.Cmt` nodes interspersed
with real forms.")
nodes, yielding `(Result (Array (Box Located)) ParseErr)`. Use
`Located.form` to reach the `Form` inside a `Located`. Comments are
preserved as `Form.Cmt` nodes interspersed with real forms.")
(defn parse [src] (Parser.parse (many-forms) src))

(doc parse-form "parses exactly one top-level `Form` form. Use
`parse` for whole-file inputs.")
(doc parse-form "parses exactly one top-level form, yielding
`(Result Located ParseErr)`. Use `parse` for whole-file inputs.")
(defn parse-form [src]
(Parser.parse
(Parser.then (skip-ws) (Parser.before (Parser.recurse &*form*) (skip-ws)))
Expand Down
9 changes: 5 additions & 4 deletions docs/Reader.html
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,9 @@ <h3 id="parse">
</pre>
<p class="doc">
<p>parses a Carp source string into an array of top-level
<code>Form</code> forms. Comments are preserved as <code>Form.Cmt</code> nodes interspersed
with real forms.</p>
nodes, yielding <code>(Result (Array (Box Located)) ParseErr)</code>. Use
<code>Located.form</code> to reach the <code>Form</code> inside a <code>Located</code>. Comments are
preserved as <code>Form.Cmt</code> nodes interspersed with real forms.</p>

</p>
</div>
Expand All @@ -455,8 +456,8 @@ <h3 id="parse-form">
(parse-form src)
</pre>
<p class="doc">
<p>parses exactly one top-level <code>Form</code> form. Use
<code>parse</code> for whole-file inputs.</p>
<p>parses exactly one top-level form, yielding
<code>(Result Located ParseErr)</code>. Use <code>parse</code> for whole-file inputs.</p>

</p>
</div>
Expand Down
8 changes: 5 additions & 3 deletions docs/carp-reader_index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ <h1>
<pre><code>(load &quot;git@github.com:carpentry-org/carp-reader@0.3.7&quot;)

(match (Reader.parse &quot;(defn hello [] (println \&quot;hi\&quot;))&quot;)
(Result.Success forms) (for [i 0 (Array.length &amp;forms)]
(println &amp;(Form.str (Box.peek (Array.unsafe-nth &amp;forms i)))))
(Result.Error e) (IO.errorln &amp;(Parser.format-error &amp;e)))
(Result.Success forms)
(for [i 0 (Array.length &amp;forms)]
(IO.println &amp;(Form.str (Located.form (Box.peek (Array.unsafe-nth &amp;forms i))))))
(Result.Error e)
(IO.errorln &amp;(Parser.format-error &amp;e)))
</code></pre>
<h3>Modules</h3>
<ul>
Expand Down
8 changes: 5 additions & 3 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ <h1>
<pre><code>(load &quot;git@github.com:carpentry-org/carp-reader@0.3.7&quot;)

(match (Reader.parse &quot;(defn hello [] (println \&quot;hi\&quot;))&quot;)
(Result.Success forms) (for [i 0 (Array.length &amp;forms)]
(println &amp;(Form.str (Box.peek (Array.unsafe-nth &amp;forms i)))))
(Result.Error e) (IO.errorln &amp;(Parser.format-error &amp;e)))
(Result.Success forms)
(for [i 0 (Array.length &amp;forms)]
(IO.println &amp;(Form.str (Located.form (Box.peek (Array.unsafe-nth &amp;forms i))))))
(Result.Error e)
(IO.errorln &amp;(Parser.format-error &amp;e)))
</code></pre>
<h3>Modules</h3>
<ul>
Expand Down
8 changes: 5 additions & 3 deletions gendocs.carp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
(load \"git@github.com:carpentry-org/carp-reader@0.3.7\")

(match (Reader.parse \"(defn hello [] (println \\\"hi\\\"))\")
(Result.Success forms) (for [i 0 (Array.length &forms)]
(println &(Form.str (Box.peek (Array.unsafe-nth &forms i)))))
(Result.Error e) (IO.errorln &(Parser.format-error &e)))
(Result.Success forms)
(for [i 0 (Array.length &forms)]
(IO.println &(Form.str (Located.form (Box.peek (Array.unsafe-nth &forms i))))))
(Result.Error e)
(IO.errorln &(Parser.format-error &e)))
```

### Modules
Expand Down