LogoMist

Parsing

PEG grammar structure, AST design, and how Mist source code is parsed.

The parser is built with pest, a PEG parser generator. Grammar rules are defined in grammar.pest (693 rules).

Key files

  • grammar.pest — PEG grammar defining the entire language syntax
  • src/parser/common/ — Parse rule → AST conversions for expressions, statements, types, declarations
  • src/parser/items/ — Parse rule → AST conversions for top-level items (structs, enums, classes, functions, traits, impls, attributes)
  • src/ast/ — AST node types (expr.rs, statement.rs, top_level.rs)
  • src/error.rs — Error types (PreAst parsing errors, Ast generation errors)

Parsing entry points

// Parse a complete program
pub fn parse<'a>(source: &'a str) -> Result<Program, ParseError<'a>>

// Parse only the module declaration
pub fn parse_module<'a>(source: &'a str) -> Result<Option<(Visibility, Identifier)>, ParseError<'a>>

Grammar Structure

The grammar follows a layered approach:

  1. Lexical rules (silent) — WHITESPACE, COMMENT, identifier, integer, float, string_lit
  2. Primary expressions — literals, paths, tuples, arrays, closures, control flow
  3. Term — prefix operators + primary + postfix operators
  4. Expression — terms joined by binary operators (via Pratt parser)
  5. Statements — variable declarations, control flow (if, while, for, match, loop), blocks
  6. Top-level items — functions, structs, enums, classes, traits, impls, type aliases, imports, module declarations, constants

AST Structure

The AST preserves source positions via Spanned<T>:

pub struct Spanned<T> {
    pub line: usize,
    pub column: usize,
    pub item: T,
}

Top-level items are wrapped as:

pub struct TopLevel(pub Spanned<TopLevelKind>, pub Vec<Attribute>);

Expressions use a fix-point representation for prefix/postfix operators:

Expression::Fix {
    initial: Box<Expression>,
    prefixes: Vec<Prefix>,
    postfixes: Vec<Postfix>,
}

Binary expressions use Pratt parsing for correct precedence:

Expression::Binary {
    lhs: Box<Expression>,
    op: String,
    rhs: Box<Expression>,
}

All operators are left-associative with a single precedence level.

On this page