Sign in

    gleam-parser

    Parser and parsing utilities for the Gleam programming language in MoonBit

    gleam
    parser
    scanner
    ast
    morphir
    Download zip
    Author
    Version
    0.3.0
    License
    Apache-2.0
    Last updated
    2 hours ago
    Downloads
    4

    #moonrockz/gleam-parser

    Parser and parsing utilities for the Gleam programming language in MoonBit. One expected user is morphir-moonbit, as a frontend that reads Gleam and a backend that writes it.

    Status: scanner, AST, parser, CST, diagnostics, syntax tree and formatter are done. The AST mirrors the Gleam compiler's untyped AST at v1.19.2; the parity oracle is the compiler itself.

    Done:

    • Scanner (tokenize): lossless tokens with trivia (whitespace, line breaks, //, /// and //// comments) that rebuild the source byte for byte; spans are UTF-8 byte offsets as in the compiler; a lexical error is a GL-SCAN-001 diagnostic with the compiler's message plus an Error token, and scanning goes on.
    • AST and JSON: the compiler's untyped AST (v1.19.2) with a canonical JSON encoder and decoder (docs/ast-json.md); a Rust oracle on gleam-core writes the same JSON, and tests/fixtures/ast prove byte equality.

    • Parser (parse_text, parse_module): a recursive-descent port of the compiler's parse.rs; on every fixture the canonical JSON equals the compiler's byte for byte, and the first error has the compiler's kind and span. A definition that does not parse is reported and skipped; the rest of the file is parsed.
    • CST (ParseResult.cst): every token grouped per definition; ModuleCst::to_source() is the text byte for byte, also with errors.
    • Formatter (format, format_parsed): gleam format's text (80 columns), from a port of the compiler's formatter on moonrockz/pretty; comments and empty lines are kept. Every one of the compiler's 893 formatter test cases and every file of the 233-file corpus formats to the binary's bytes (tests/format).

      inspect(
      @gleam.format("pub fn main(){\n io.println( \"hi\" )\n}\n"),
      content="pub fn main() {\n io.println(\"hi\")\n}\n",
      )

    • Dialect (Dialect::gleam_1_19()): what the parser accepts.
    • Config (Config::default(), Config::load()): the dialect and the fuel budget (the recursion limit, 100 units by default), from a gleam-parser.toml file, GLEAM_PARSER_* variables and the caller, merged with with_fallback.
    • Syntax tree (NodeRef, Tree, NodePath): a read-only node model over the AST with parent links, position lookup and seven traversal styles: walk, fold, reduce, Visitor, pull events, push events and TreeCursor; every traversal uses an explicit stack.
    • Report (render_plain, render_terminal, encode_diagnostics): the compiler's diagnostic layout, with colours, or as JSON.
    • Parity: on a pinned corpus of 25 published packages (233 files), all 233 files give the compiler's AST byte for byte (mise run test:parity); 44 rejection fixtures check the accept and reject verdicts and the first error against the compiler (mise run test:rejection).

    test {
    let r = @gleam.parse_text("import gleam/io\n\npub fn main() {\n io.println(\"hi\")\n}\n")
    inspect(r.module_.definitions.length(), content="2")
    inspect(r.has_errors(), content="false")
    }

    Find the node at a byte offset and its path (from a tested doc example):

    test {
    let tree = @gleam.Tree::new(@gleam.parse_text("pub fn add(a, b) {\n a + b\n}\n"))
    // Byte 25 is the `b` in `a + b`.
    let b = tree.node_at(25).unwrap()
    inspect("\{b.category()}/\{b.kind()}", content="expression/var")
    inspect(tree.node_path(b).unwrap(), content="definitions[0].body[0].expression[0].right[0]")
    }

    Planned:

    • Printer and formatter: Gleam source from an AST, gleam format parity.

    #Installation

    moon add moonrockz/gleam-parser

    In your package's moon.pkg:

    import { "moonrockz/gleam-parser" @gleam, }

    #Development

    • mise run check: info, lint, format and all tests.
    • mise run test:targets: the library on wasm, wasm-gc, js and native.
    • mise run test:parity and mise run test:rejection: parity with the Gleam compiler on the corpus and on the rejection fixtures (see AGENTS.md).
    • See AGENTS.md for conventions and docs/cookbook/ for tested examples.

    Arg

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ArgNames

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Assert

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    AssignName

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Assignment

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    AssignmentKind

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    BinOp

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    BitArrayOption

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    BitArraySegment

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    BitArraySize

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Budget

    Fuel: the recursion budget (Budget, at least 1; default_budget is 100 units), the operation names an exhausted budget reports (Spent), and the error FuelExhausted.

    CallArg

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Clause

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ClauseGuard

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Comment

    The scanner: tokens, trivia and lexical errors.

    CommentKind

    The scanner: tokens, trivia and lexical errors.

    Config

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    ConfigError

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    Constant

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Control

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    CustomType

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    DecodeError

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Definition

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    DefinitionCst

    The CST: every token grouped per definition (ModuleCst::to_source() is the text byte for byte; a Skipped definition is a run the parser reported and skipped).

    DefinitionKind

    The CST: every token grouped per definition (ModuleCst::to_source() is the text byte for byte; a Skipped definition is a run the parser reported and skipped).

    Deprecation

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Diagnostic

    Diagnostics: severity, labels and the problem record.

    Dialect

    Dialects: what the parser accepts (Dialect::gleam_1_19() is the default) and the deprecation Rules it warns about.

    Documentation

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    EnterEvent

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Environment

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    Event

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    EventReader

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    EventSource

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Expr

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    External

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    FormatError

    Why format gives no text.

    Fuel

    Fuel: the recursion budget (Budget, at least 1; default_budget is 100 units), the operation names an exhausted budget reports (Spent), and the error FuelExhausted.

    FuelExhausted

    Fuel: the recursion budget (Budget, at least 1; default_budget is 100 units), the operation names an exhausted budget reports (Spent), and the error FuelExhausted.

    Function

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    FunctionLiteralKind

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Handler

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    ImplicitCallArgOrigin

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Import

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ImportAlias

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    IncorrectNamePosition

    The parser: a module from tokens, with recovery per definition. A ParseResult holds the AST (module_), extra, warnings, the cst and the diagnostics; ParseError is what the snippet parsers raise.

    IntOperator

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Keyword

    The scanner: tokens, trivia and lexical errors.

    Label

    Diagnostics: severity, labels and the problem record.

    LeaveEvent

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    LexicalErrorType

    The scanner: tokens, trivia and lexical errors.

    Module

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ModuleConstant

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ModuleCst

    The CST: every token grouped per definition (ModuleCst::to_source() is the text byte for byte; a Skipped definition is a run the parser reported and skipped).

    ModuleExtra

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    NodePath

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    NodeRef

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Operation

    Fuel: the recursion budget (Budget, at least 1; default_budget is 100 units), the operation names an exhausted budget reports (Spent), and the error FuelExhausted.

    OracleOutput

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    ParseError

    The parser: a module from tokens, with recovery per definition. A ParseResult holds the AST (module_), extra, warnings, the cst and the diagnostics; ParseError is what the snippet parsers raise.

    ParseErrorDetails

    The parser: a module from tokens, with recovery per definition. A ParseResult holds the AST (module_), extra, warnings, the cst and the diagnostics; ParseError is what the snippet parsers raise.

    ParseErrorType

    The parser: a module from tokens, with recovery per definition. A ParseResult holds the AST (module_), extra, warnings, the cst and the diagnostics; ParseError is what the snippet parsers raise.

    ParseResult

    The parser: a module from tokens, with recovery per definition. A ParseResult holds the AST (module_), extra, warnings, the cst and the diagnostics; ParseError is what the snippet parsers raise.

    Parsed

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Partial

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    PathStep

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Pattern

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Position

    Spans (UTF-8 byte offsets) and positions (1-based line and column).

    Publicity

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    RecordBeingUpdated

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    RecordConstructor

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    RecordConstructorArg

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    RecordUpdateArg

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Rule

    Dialects: what the parser accepts (Dialect::gleam_1_19() is the default) and the deprecation Rules it warns about.

    Severity

    Diagnostics: severity, labels and the problem record.

    Source

    Configuration: Config (dialect, fuel) from defaults, a TOML text, the environment and the caller, merged with with_fallback; Config::load reads gleam-parser.toml and GLEAM_PARSER_*.

    SourceText

    Source text with byte, UTF-16 and line/column lookups.

    SpannedString

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Spent

    Fuel: the recursion budget (Budget, at least 1; default_budget is 100 units), the operation names an exhausted budget reports (Spent), and the error FuelExhausted.

    SrcSpan

    Spans (UTF-8 byte offsets) and positions (1-based line and column).

    Statement

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    StringPrefixLeftSideAssignment

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TailPattern

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Target

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TargetedDefinition

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TodoKind

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Token

    The scanner: tokens, trivia and lexical errors.

    TokenKind

    The scanner: tokens, trivia and lexical errors.

    TokenStream

    The scanner: tokens, trivia and lexical errors.

    Tree

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    TreeCursor

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Trivia

    The scanner: tokens, trivia and lexical errors.

    TypeAlias

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAst

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstConstructor

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstConstructorName

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstFn

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstHole

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstTuple

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    TypeAstVar

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    UnicodeEscapeError

    The scanner: tokens, trivia and lexical errors.

    UnqualifiedImport

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Use

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    UseAssignment

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    Visitor

    The syntax tree (v0.2): a read-only node model (NodeRef), parent links and positions (Tree), paths (NodePath) and seven traversals: walk, fold, reduce, Visitor with accept, EventReader (pull), push_events with Handler (push) and TreeCursor. Every traversal uses an explicit stack, so no depth overflows and no fuel is spent.

    Warning

    The AST: a mirror of the Gleam compiler's untyped AST (v1.19.2), with canonical JSON (docs/ast-json.md).

    accept

    Walk with a Visitor (see @syntax.accept).

    canonical

    fn canonical(json : Json) -> String

    Canonical JSON text of an encoded AST value (sorted keys, no whitespace).

    default_budget

    The default fuel budget, 100 units (see @fuel.default_budget).

    diagnostic_description

    fn diagnostic_description(code : String) -> String?

    The one-line description of a diagnostic code (GL-SCAN-001, …), or None for an unknown code. The table is in AGENTS.md > Diagnostics.

    encode_diagnostics

    Diagnostics as JSON (gleam-parser's own shape).

    encode_expr

    encode_oracle_output

    encode_parsed

    fold

    Walk with an accumulator (see @syntax.fold).

    format

    Format Gleam source as gleam format does (see @format.format): 80 columns, two spaces of indentation, comments and empty lines kept. Raises ParseFailed with the error diagnostics when the text has a syntax error.

    test {
    inspect(@gleam.format("const x = 1\n"), content="const x = 1\n")
    }

    format_parsed

    Format a parse result (see @format.format_parsed).

    kind_table

    fn kind_table() -> Array[(String, String, Array[String])]

    Every node type as (category, kind, fields) (see @syntax.kind_table).

    parse_float_value

    fn parse_float_value(value : String) -> Double?

    The number a Float literal denotes (1., 1.e3, 1.0e-3, _).

    parse_int_value

    fn parse_int_value(value : String) ->
    BigInt
    ?

    The number an Int literal denotes (sign, radix prefix, _ separators).

    parse_module

    Parse a token stream into a module (see @parser.parse_module).

    parse_text

    Parse Gleam source text into a module, with recovery per definition. config sets the dialect and the fuel budget; see Config.

    test {
    let r = @gleam.parse_text("pub fn main() {\n io.println(\"hi\")\n}\n")
    inspect(r.module_.definitions.length(), content="1")
    inspect(r.has_errors(), content="false")
    }

    push_events

    Pull every event from source and push it to handler (see @syntax.push_events).

    reduce

    Reduce the tree to one value, bottom up (see @syntax.reduce).

    reduce_with_fields

    reduce with each child's step next to its result (see @syntax.reduce_with_fields).

    render_plain

    Render a diagnostic as the Gleam compiler prints it (no colours).

    render_terminal

    Render a diagnostic with ANSI colours.

    tokenize

    Scan source into tokens with trivia and diagnostics. The scan is lossless: TokenStream::to_source() is the text.

    tokenize_text

    tokenize of a SourceText built from text.

    version

    fn version() -> String

    The version of gleam-parser, the same as version in moon.mod. mise run release:prepare rewrites the string below; tests/bdd checks that it equals moon.mod.

    test {
    inspect(@gleam.version().split(".").count(), content="3")
    }

    walk

    Visit every node below root in pre-order (see @syntax.walk).

    test {
    let root = @gleam.NodeRef::of_result(
    @gleam.parse_text("pub fn f(x) {\n x\n}\n"),
    )
    let kinds = []
    @gleam.walk(root, n => {
    kinds.push(n.kind())
    Continue
    })
    inspect(kinds.join(" "), content="module function arg expression var")
    }

    Source Files