parser

    AST and parsers for the MoonBit programming language

    parser
    lexer
    AST
    MoonBit
    Download zip
    Version
    0.4.8
    License
    Apache-2.0
    Last updated
    11 hours ago
    Downloads
    262K

    #moonbitlang/parser

    Note: This module is highly experimental and unstable. Use with caution.

    A parser implementation for the MoonBit programming language, written in MoonBit, providing lexical analysis and syntax parsing capabilities.

    This module defines the Abstract Syntax Tree (AST) and provides parsers for MoonBit source code. It includes both a hand-written LL(k) parser with error recovery and an LR(1) parser generated by moonyacc.

    #Project Structure

    . ├── basic/ # shared locations, config, and diagnostic helpers ├── tokens/ # token definitions generated from yacc_parser/parser.mbty ├── lexer/ # lexical analysis components ├── attribute/ # attribute syntax and parser support ├── syntax/ # AST for MoonBit source code ├── handrolled_parser/ # hand-written LL(k) parser with error recovery ├── yacc_parser/ # moonyacc LR parser for MoonBit source files ├── mbti_ast/ # AST for .mbti interface files ├── mbti_parser/ # moonyacc LR parser for .mbti interface files ├── moon_config/ # moon.mod and moon.pkg configuration parsing ├── fmt/ # formatter library ├── cmd/ # command-line tools │ ├── moonfmt/ # formatter executable │ ├── mq/ # package query executable │ └── wasm/mq/ # WebAssembly mq target └── top.mbt # root package parsing entry points

    #Package Guides

    #Parsing .mbtx files

    Use parse_mbtx_string(source, name?, parser?) for files with optional configuration frontmatter. It returns (Mbtx, Array[@basic.Report]). Mbtx contains header (a moon_config.ParseResult?) and body (the source AST); the reports combine header and body diagnostics. None distinguishes no header from an explicitly empty header. parse_string continues to parse ordinary source.

    A header begins with a first line of at least three dashes, optionally preceded by a BOM, and ends with a line of at least as many dashes. LF and CRLF are supported; an unclosed header extends to EOF. Header syntax is parsed without imposing moon.pkg field validation, so script settings such as permissions(...) are retained. Header and body diagnostics retain original file positions. Configuration conditions are preserved without backend selection; derive attributes are preserved without generating implementations.

    ///|
    test "parse mbtx frontmatter" {
    let source = "---\nexperimental = true\n---\nlet value = reb\"[a-z]+\""
    let (result, reports) = @parser.parse_mbtx_string(source, name="example.mbtx")
    assert_true(result.header is Some(_))
    assert_eq(reports.length(), 0)
    assert_eq(result.body.length(), 1)
    }

    #Usage

    ///|
    test {
    let source =
    #| let number = 123
    #| fn add(a: Int, b: Int) -> Int {
    #| a + b
    #| }
    #| enum Color {
    #| Red
    #| Green
    #| Blue
    #| }
    #| struct Point {
    #| x: Int
    #| y: Int
    #| }
    let (impls, _) = @parser.parse_string(source)
    json_inspect(impls.map(impl_ => impl_.json_repr()), content=[
    {
    "kind": "Impl::TopLetDef",
    "loc": null,
    "children": {
    "binder": {
    "kind": "Binder",
    "loc": null,
    "children": { "name": "number" },
    },
    "ty": null,
    "expr": {
    "kind": "Expr::Constant",
    "loc": null,
    "children": {
    "constant": {
    "kind": "Constant::Int",
    "loc": null,
    "children": { "value": "123" },
    },
    },
    },
    "vis": { "kind": "Visibility::Default", "loc": null, "children": {} },
    "is_constant": false,
    "is_declare": false,
    "attrs": {
    "kind": "Impl::TopLetDef::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    {
    "kind": "Impl::TopFuncDef",
    "loc": null,
    "children": {
    "fun_decl": {
    "kind": "FunDecl",
    "loc": null,
    "children": {
    "type_name": null,
    "name": {
    "kind": "Binder",
    "loc": null,
    "children": { "name": "add" },
    },
    "has_error": null,
    "is_async": null,
    "decl_params": {
    "kind": "FunDecl::ParameterList",
    "loc": null,
    "children": [
    {
    "kind": "Parameter::Positional",
    "loc": null,
    "children": {
    "binder": {
    "kind": "Binder",
    "loc": null,
    "children": { "name": "a" },
    },
    "ty": {
    "kind": "Type::Name",
    "loc": null,
    "children": {
    "constr_id": {
    "kind": "ConstrId",
    "loc": null,
    "children": {
    "id": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "Int" },
    },
    },
    },
    "tys": {
    "kind": "Type::Name::TypeList",
    "loc": null,
    "children": [],
    },
    },
    },
    },
    },
    {
    "kind": "Parameter::Positional",
    "loc": null,
    "children": {
    "binder": {
    "kind": "Binder",
    "loc": null,
    "children": { "name": "b" },
    },
    "ty": {
    "kind": "Type::Name",
    "loc": null,
    "children": {
    "constr_id": {
    "kind": "ConstrId",
    "loc": null,
    "children": {
    "id": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "Int" },
    },
    },
    },
    "tys": {
    "kind": "Type::Name::TypeList",
    "loc": null,
    "children": [],
    },
    },
    },
    },
    },
    ],
    },
    "quantifiers": {
    "kind": "FunDecl::QuantifierList",
    "loc": null,
    "children": [],
    },
    "return_type": {
    "kind": "Type::Name",
    "loc": null,
    "children": {
    "constr_id": {
    "kind": "ConstrId",
    "loc": null,
    "children": {
    "id": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "Int" },
    },
    },
    },
    "tys": {
    "kind": "Type::Name::TypeList",
    "loc": null,
    "children": [],
    },
    },
    },
    "error_type": {
    "kind": "ErrorType::NoErrorType",
    "loc": null,
    "children": {},
    },
    "vis": {
    "kind": "Visibility::Default",
    "loc": null,
    "children": {},
    },
    "attrs": {
    "kind": "FunDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    "where_clause": null,
    "decl_body": {
    "kind": "DeclBody::DeclBody",
    "loc": null,
    "children": {
    "expr": {
    "kind": "Expr::Infix",
    "loc": null,
    "children": {
    "op": {
    "kind": "Var",
    "loc": null,
    "children": {
    "name": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "+" },
    },
    },
    },
    "lhs": {
    "kind": "Expr::Ident",
    "loc": null,
    "children": {
    "id": {
    "kind": "Var",
    "loc": null,
    "children": {
    "name": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "a" },
    },
    },
    },
    },
    },
    "rhs": {
    "kind": "Expr::Ident",
    "loc": null,
    "children": {
    "id": {
    "kind": "Var",
    "loc": null,
    "children": {
    "name": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "b" },
    },
    },
    },
    },
    },
    },
    },
    },
    },
    },
    },
    {
    "kind": "Impl::TopTypeDef",
    "loc": null,
    "children": {
    "value": {
    "kind": "TypeDecl",
    "loc": null,
    "children": {
    "tycon": "Color",
    "params": {
    "kind": "TypeDecl::ParamList",
    "loc": null,
    "children": [],
    },
    "components": {
    "kind": "TypeDesc::Variant",
    "loc": null,
    "children": {
    "value": {
    "kind": "TypeDesc::Variant::ConstrList",
    "loc": null,
    "children": [
    {
    "kind": "ConstrDecl",
    "loc": null,
    "children": {
    "name": {
    "kind": "ConstrName",
    "loc": null,
    "children": { "name": "Red" },
    },
    "args": null,
    "tag": null,
    "attrs": {
    "kind": "ConstrDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    {
    "kind": "ConstrDecl",
    "loc": null,
    "children": {
    "name": {
    "kind": "ConstrName",
    "loc": null,
    "children": { "name": "Green" },
    },
    "args": null,
    "tag": null,
    "attrs": {
    "kind": "ConstrDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    {
    "kind": "ConstrDecl",
    "loc": null,
    "children": {
    "name": {
    "kind": "ConstrName",
    "loc": null,
    "children": { "name": "Blue" },
    },
    "args": null,
    "tag": null,
    "attrs": {
    "kind": "ConstrDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    ],
    },
    },
    },
    "attrs": {
    "kind": "TypeDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    "type_vis": {
    "kind": "Visibility::Default",
    "loc": null,
    "children": {},
    },
    "is_declare": false,
    "deriving": {
    "kind": "TypeDecl::DerivingList",
    "loc": null,
    "children": [],
    },
    },
    },
    },
    },
    {
    "kind": "Impl::TopTypeDef",
    "loc": null,
    "children": {
    "value": {
    "kind": "TypeDecl",
    "loc": null,
    "children": {
    "tycon": "Point",
    "params": {
    "kind": "TypeDecl::ParamList",
    "loc": null,
    "children": [],
    },
    "components": {
    "kind": "TypeDesc::Record",
    "loc": null,
    "children": {
    "value": {
    "kind": "TypeDesc::Record::FieldList",
    "loc": null,
    "children": [
    {
    "kind": "FieldDecl",
    "loc": null,
    "children": {
    "name": {
    "kind": "FieldName",
    "loc": null,
    "children": { "label": "x" },
    },
    "ty": {
    "kind": "Type::Name",
    "loc": null,
    "children": {
    "constr_id": {
    "kind": "ConstrId",
    "loc": null,
    "children": {
    "id": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "Int" },
    },
    },
    },
    "tys": {
    "kind": "Type::Name::TypeList",
    "loc": null,
    "children": [],
    },
    },
    },
    "mut": false,
    "vis": {
    "kind": "Visibility::Default",
    "loc": null,
    "children": {},
    },
    "attrs": {
    "kind": "FieldDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    {
    "kind": "FieldDecl",
    "loc": null,
    "children": {
    "name": {
    "kind": "FieldName",
    "loc": null,
    "children": { "label": "y" },
    },
    "ty": {
    "kind": "Type::Name",
    "loc": null,
    "children": {
    "constr_id": {
    "kind": "ConstrId",
    "loc": null,
    "children": {
    "id": {
    "kind": "LongIdent::Ident",
    "loc": null,
    "children": { "value": "Int" },
    },
    },
    },
    "tys": {
    "kind": "Type::Name::TypeList",
    "loc": null,
    "children": [],
    },
    },
    },
    "mut": false,
    "vis": {
    "kind": "Visibility::Default",
    "loc": null,
    "children": {},
    },
    "attrs": {
    "kind": "FieldDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    },
    },
    ],
    },
    },
    },
    "attrs": {
    "kind": "TypeDecl::AttrList",
    "loc": null,
    "children": [],
    },
    "doc": "",
    "type_vis": {
    "kind": "Visibility::Default",
    "loc": null,
    "children": {},
    },
    "is_declare": false,
    "deriving": {
    "kind": "TypeDecl::DerivingList",
    "loc": null,
    "children": [],
    },
    },
    },
    },
    },
    ])
    }

    You can also explore the parsing results using the AST Explorer.

    #Build & Test

    This project uses the MoonBit build system:

    moon update moon check moon test

    #Contributing

    We welcome contributions to this project! Please see CONTRIBUTING.md for guidelines on how to contribute and report bugs.

    Mbtx

    A separately parsed configuration header and source body, with original file locations.

    Parser

    pub(all) enum Parser {
    MoonYacc
    Handrolled
    }

    parse_mbtx_string

    fn parse_mbtx_string(source : String, name? : String, parser? : Parser) -> (Mbtx, Array[
    Report
    ])

    Parse a configuration header and source body. Reports include header errors/warnings and body errors, with original file locations.

    parse_string

    Source Files