Skip to content

Parser

The parser is hand-rolled recursive descent with Pratt expression precedence. It builds a rowan GreenNode incrementally and produces a ParseResult containing the tree and any errors.

It lives in crates/mty-syntax/src/parser/.

Module layout

File Productions
mod.rs Parser struct, cursor primitives, file/expr/type/pattern entry points
items.rs top-level items (fn, struct, enum, type alias, impl, trait, const, use, mod, package)
agents.rs agent, protocol, supervisor, on Msg, on_fail
concurrency.rs arena, task scope, budget, sandbox, spawn, detach, join
exprs.rs expression Pratt with !Msg, ?Msg, @dur, ? postfix
extern_.rs extern c, extern js, export c fn, export fn
macros.rs macro declaration
paths.rs path expressions and path types, generic args
patterns.rs match patterns (literal, ident, wildcard, tuple, struct, enum, range, ref, binding)
recovery.rs error recovery helpers
stmts.rs let and expr; statements
types.rs type expressions, T!E and T!{A,B} sugar
unsafe_.rs unsafe { ... }, unsafe fn, requires clauses

Cursor primitives

peek(&self) -> SyntaxKind
peek_n(&self, n: usize) -> SyntaxKind
at(&self, kind) -> bool
at_set(&self, set: &[SyntaxKind]) -> bool
bump_any(&mut self)
bump(&mut self, expected: SyntaxKind)
eat(&mut self, kind) -> bool
expect(&mut self, kind) -> bool
skip_trivia(&mut self)

All productions are written against these. Nodes are opened with start_node / start_node_at(checkpoint, ...) and closed with finish_node.

Pratt expressions

exprs::expr is a Pratt parser with a fixed precedence table.

The normative precedence table lives in v1.0-rc.md ยง11.1.1 (as of v1.0-RC3). This internals doc no longer carries the authoritative list; it summarises what the Rust implementation covers:

  • assignment and compound assignment (=, +=, ...);
  • ranges (.., ..=);
  • short-circuit logical (||, &&);
  • equality and comparison;
  • bitwise (|, ^, &, <<, >>);
  • arithmetic (+, -, *, /, %);
  • prefix unary (-, !, *, &, &mut);
  • postfix: calls, field access, indexing, ? propagation, ?Msg(args) ask, !Msg(args) send, @duration, as cast.

The binding-power function is exprs::infix_bp; right-associativity of assignment + compound-assignment is in exprs::infix_right_assoc.

Recovery

Top-level recovery is "bump and report": when no item production matches, the parser records an unexpected token error and consumes one token before retrying. The depth limit produces MT0030.

Slice 2 will add expression-level recovery so that an error inside a function body does not poison the rest of the file.

Entry points

pub fn parse(src: &str) -> ParseResult;
pub fn parse_type(src: &str) -> ParseResult;
pub fn parse_pattern(src: &str) -> ParseResult;
pub fn parse_expr(src: &str) -> ParseResult;

The latter three exist for testing parser fragments.

See also