marianoguerra/shrubbery/ast does not have a README file

    Node

    One node: what it is, where it came from, and how to write it back.

    Node::canonical

    fn Node::canonical(self : Node) -> String

    The canonical text form, for comparing our parse against the reference's.

    This is the S-expression the reference produces, written with @sexp's escaping so that both sides of the comparison are all-ASCII and an encoding difference in transit cannot look like a parse difference.

    Node::children

    fn Node::children(self : Node) -> Array[Node]

    The children of a compound node, or an empty array for a leaf.

    Node::to_source

    fn Node::to_source(self : Node) -> String

    The source text this node came from.

    Node::write_canonical

    fn Node::write_canonical(self : Node, buf : StringBuilder) -> Unit

    Node::write_source

    fn Node::write_source(self : Node, buf : StringBuilder) -> Unit

    The source text this node came from, rebuilt from its metadata.

    Emission order is the field order of @raw.Meta and is load-bearing -- prefix, inner prefix, raw, then children or opaque_content, then tail, inner suffix, suffix -- with opaque_raw superseding the middle three.

    Shrub

    pub(all) enum Shrub {
    Id(String)
    Kw(String)
    Op(String)
    Lit(
    Datum
    )
    Parsed(
    Datum
    )
    Group(Array[Node])
    Block(Array[Node])
    Alts(Array[Node])
    Parens(Array[Node])
    Brackets(Array[Node])
    Braces(Array[Node])
    Quotes(Array[Node])
    Multi(Array[Node])
    }

    A parsed shrubbery.

    The shape mirrors the reference's S-expression representation exactly, because that representation IS the interface: it is what #{...} escapes speak, what the parse oracle compares, and what a language built on this notation will pattern-match. A more strongly typed tree -- one where a group's optional block and alternatives were separate fields, so that the grammar's two structural laws were unrepresentable rather than merely true -- was the alternative, and it would have made the parser port a translation rather than a transcription of a mutual recursion with fourteen threaded state fields. The laws are stated below and checked by the oracle instead.

    The laws, for the record:

    • Block appears only as the last item of a Group, or as the second-to-last with Alts after it.
    • Alts appears only as the last item of a Group, and contains only Blocks.
    • A Group is never empty.

    Shrub::tag

    fn Shrub::tag(self : Shrub) -> String

    The reference's tag for this node, for messages and for the oracle.

    Source Files

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io