Pratt parser for CJC source code.
This crate implements a Pratt (top-down operator precedence) parser that
consumes the token stream produced by [cjc_lexer] and builds a complete
AST defined in [cjc_ast].
Quick start
The easiest way to lex and parse in one step is the convenience
function [parse_source]:
let (program, diags) = cjc_parser::parse_source("fn main() { 42 }");
assert!(!diags.has_errors());
For finer control, create a [Parser] from a pre-existing token vector:
let (tokens, _) = cjc_lexer::Lexer::new(src).tokenize();
let parser = cjc_parser::Parser::new(tokens);
let (program, diags) = parser.parse_program();
Architecture
The parser uses binding-power levels defined in the private [prec] module
to resolve operator precedence. The main expression driver is
[Parser::parse_expr_bp], which alternates between prefix/atom parsing
and an infix/postfix loop governed by the current binding power.
Declarations (functions, structs, enums, traits, impls, imports, etc.) are
dispatched from [Parser::parse_program] via [Parser::parse_decl].
Error recovery uses the [Parser::synchronize] method, which skips tokens
until a well-known synchronization point (semicolon, closing brace, or
declaration-starting keyword) is reached.