moonrockz/krueger/dialect does not have a README file

    AttributeSyntax

    pub(all) enum AttributeSyntax {
    Off
    DocComment
    } derive(Eq,
    Debug
    )

    Whether attributes in doc comments are parsed.

    Dialect

    pub(all) struct Dialect {
    name : String
    rules :
    HashSet
    [Rule]
    operators : Array[OperatorDef]
    reserved_words : Array[String]
    operator_symbols : Array[String]
    attributes : AttributeSyntax
    core_package : Bool
    }

    A variant of Elm: which rejection rules run, and the extension data (operator table, extra reserved words, extra operator symbols) the scanner and the parser read. The AST shape is elm-syntax 7.3.9 in every dialect.

    • An extra operator symbol must start with a character the lexer already treats as a symbol (+ - / * = . < > : & | ^ ?) and must not start with -- (a line comment).
    • An extra reserved word must not be alias, infix or effect: the parser reads those by name.
    • { ..d, field: value } shares rules and operators with d; copy them before changing either.

    Build the scanner and the parser with the same dialect. To make a custom dialect, start from a built-in one. This one adds an operator <=>. The operator needs an entry in operators (for the parser) and in operator_symbols (for the lexer, which otherwise reads <= and >):

    test {
    let base = @dialect.Dialect::elm_0_19_1()
    let dialect = {
    ..base,
    name: "my-elm",
    operators: [
    ..base.operators,
    { symbol: "<=>", precedence: 4, direction: Non, },
    ],
    operator_symbols: ["<=>"],
    }
    inspect(dialect.validate().length(), content="0")
    let source = @scanner.SourceText::new(
    "module Main exposing (..)\n\nx =\n a <=> b\n",
    )
    let plain = @parser.parse_module(
    source,
    @scanner.DefaultScanner::new(dialect=base),
    dialect=base,
    )
    inspect(plain.diagnostics[0].title, content="UNKNOWN OPERATOR")
    let custom = @parser.parse_module(
    source,
    @scanner.DefaultScanner::new(dialect~),
    dialect~,
    )
    inspect(custom.diagnostics.length(), content="0")
    }

    An extra reserved word stops a name from being used. To turn a rule off, give the dialect a new rule set; do not change the set of the base:

    test {
    let base = @dialect.Dialect::elm_0_19_1()
    let rules = base.rules.copy()
    rules.remove(LeadingZero)
    let dialect = { ..base, rules, reserved_words: ["forall"], }
    inspect(base.has(LeadingZero), content="true")
    inspect(dialect.has(LeadingZero), content="false")
    let parse = (text : String) => {
    @parser.parse_module(
    @scanner.SourceText::new(text),
    @scanner.DefaultScanner::new(dialect~),
    dialect~,
    ).diagnostics
    }
    inspect(parse("module Main exposing (..)\n\nx = 007\n").length(), content="0")
    let errors = parse("module Main exposing (..)\n\nforall = 1\n")
    inspect(
    errors[0].message,
    content="Malformed function declaration: expected a function name, found `forall`",
    )
    }

    Dialect::elm_0_19_1

    fn Dialect::elm_0_19_1() -> Dialect

    The default dialect: rejects what elm make 0.19.1 rejects as syntax.

    It enables every rule except TitlecaseNameStart, has the standard operator table, and reads doc-comment attributes. core_package is false, so effect modules and infix declarations are errors.

    test {
    let dialect = @dialect.Dialect::elm_0_19_1()
    inspect(dialect.name, content="elm-0.19.1")
    inspect(dialect.has(PortInNormalModule), content="true")
    debug_inspect(
    dialect.operator("|>"),
    content=(
    #|Some({ symbol: "|>", precedence: 1, direction: Left })
    ),
    )
    }

    Dialect::elm_syntax_7_3_9

    fn Dialect::elm_syntax_7_3_9() -> Dialect

    Rejects exactly what elm-syntax 7.3.9 rejects.

    Use it to compare output with elm-syntax: the parity harness scores in this dialect. It accepts some syntax that elm make rejects, for example 007, 0X1F and 1e.

    test {
    let source = @scanner.SourceText::new(
    "module Main exposing (..)\n\nx =\n 0X1F\n",
    )
    let parse = (dialect : @dialect.Dialect) => {
    @parser.parse_module(
    source,
    @scanner.DefaultScanner::new(dialect~),
    dialect~,
    ).diagnostics.length()
    }
    inspect(parse(@dialect.Dialect::elm_syntax_7_3_9()), content="0")
    inspect(parse(@dialect.Dialect::elm_0_19_1()), content="1")
    }

    Dialect::has

    fn Dialect::has(self : Dialect, rule : Rule) -> Bool

    Whether the dialect enables rule.

    Dialect::operator

    fn Dialect::operator(self : Dialect, symbol : String) -> OperatorDef?

    The operator table entry for symbol, if the dialect has one.

    Dialect::validate

    fn Dialect::validate(self : Dialect) -> Array[String]

    Problems with the dialect's extension data, as messages (empty when it is valid). The scanner and parser do not check these; call this when a dialect comes from outside (a config file, a CLI flag).

    OperatorDef

    pub(all) struct OperatorDef {
    symbol : String
    precedence : Int
    direction :
    InfixDirection

    } derive(Eq,
    Debug
    )

    An infix operator: its symbol, precedence (1 to 9) and direction.

    Rule

    pub(all) enum Rule {
    LeadingZero
    EmptyHex
    BadUnicodeEscape
    CharLength
    IndentedContinuation
    LetDeclarationColumn
    ModuleLevelColumn
    SpacedOperatorName
    UppercaseHexPrefix
    ExponentWithoutDigits
    ImportColumn
    NonAsciiDigitInName
    TitlecaseNameStart
    EffectModule
    InfixDeclaration
    DuplicateEffectKey
    PortInNormalModule
    } derive(Eq, Hash,
    Debug
    )

    A rejection rule: one class of syntax that a dialect rejects. A rule only runs when the dialect enables it.

    A diagnostic from a rule names it as [rule: <name>] (see Rule::name). Dialect::has tells whether a dialect enables a rule.

    test {
    let elm = @dialect.Dialect::elm_0_19_1()
    let oracle = @dialect.Dialect::elm_syntax_7_3_9()
    // Both reject a char literal with two characters.
    inspect(elm.has(CharLength) && oracle.has(CharLength), content="true")
    // Only `elm make` rejects `007`.
    inspect(elm.has(LeadingZero), content="true")
    inspect(oracle.has(LeadingZero), content="false")
    inspect(@dialect.Rule::LeadingZero.name(), content="leading-zero")
    }

    Rule::name

    fn Rule::name(self : Rule) -> String

    Kebab-case name, shown in diagnostics as [rule: <name>].

    standard_operators

    fn standard_operators() -> Array[OperatorDef]

    The infix operators of Elm 0.19.1 as elm-syntax 7.3.9 knows them, including </> and <?> from elm/url.

    Source Files

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io