Skip to main content

relix/
lib.rs

1//! # Relix
2//!
3//! A Pratt parser library for a custom language with first-class support for
4//! expressions, statements, and type annotations.
5//!
6//! Relix provides a complete lexing and parsing pipeline built on
7//! [Pratt parsing](https://en.wikipedia.org/wiki/Pratt_parser) (top-down
8//! operator precedence) techniques. It tokenizes source code via a
9//! regex-driven lexer, then builds an abstract syntax tree (AST) using
10//! configurable binding-power tables.
11//!
12//! ## Quick start
13//!
14//! ```
15//! use relix::parser::parse;
16//!
17//! let source = r#"
18//!     let x = 10;
19//!     fn add(a: number, b: number): number {
20//!         a + b;
21//!     }
22//! "#;
23//!
24//! let ast = parse(source).unwrap();
25//! println!("{:#?}", ast);
26//! ```
27//!
28//! ## Architecture
29//!
30//! The library is organised into three layers:
31//!
32//! | Layer   | Module               | Purpose                               |
33//! |---------|----------------------|---------------------------------------|
34//! | Lexer   | [`lexer`]            | Regex-based tokenization              |
35//! | AST     | [`ast`]              | Expression, statement, and type nodes |
36//! | Parser  | [`parser`]           | Pratt-parser driver and handlers      |
37//!
38//! ### Lexer
39//!
40//! The [`lexer`] module converts raw source text into a flat sequence of
41//! [`Token`](lexer::Token) values. It recognises literals (numbers, strings,
42//! identifiers), operators, punctuation, and reserved keywords.
43//!
44//! ### AST
45//!
46//! The [`ast`] module defines the node types that make up the abstract syntax
47//! tree. Every construct the parser can produce is represented as a variant of
48//! one of three top-level enums:
49//!
50//! - [`ast::Expr`] — expression nodes (literals, binary ops, calls, …)
51//! - [`ast::Stmt`] — statement nodes (variable declarations, functions, …)
52//! - [`ast::Type`] — type annotation nodes (symbol types, list types)
53//!
54//! ### Parser
55//!
56//! The [`parser`] module ties everything together. The main entry point is
57//! [`parser::parse`], which accepts a source string and returns a
58//! [`BlockStmt`](ast::BlockStmt) representing the entire program.
59//!
60//! Internally the parser uses Pratt parsing with configurable **nud** (null
61//! denotation), **led** (left denotation), and **binding power** tables
62//! registered via [`parser::lookups::Lookups`].
63//!
64//! ## Supported language features
65//!
66//! - **Expressions**: arithmetic, logical, comparison, assignment, member
67//!   access, computed access, function calls, array literals, range
68//!   expressions, anonymous functions, `new` instantiation
69//! - **Statements**: variable declarations (`let`/`const`), function
70//!   declarations, `if`/`else`, `foreach` loops, `import`, class declarations,
71//!   block statements
72//! - **Type annotations**: symbol types (`number`, `string`) and list types
73//!   (`[]T`)
74//!
75//! ## Extending the parser
76//!
77//! New syntax can be added by registering additional nud/led handlers in the
78//! [`Lookups`](parser::lookups::Lookups) table. See [`parser::lookups`] for
79//! details on binding powers and handler signatures.
80
81pub mod lexer;
82pub mod ast;
83pub mod parser;
84pub mod error;
85
86pub use error::RelixError;
87pub use parser::lookups;
88pub use parser::expr as exprs;
89pub use parser::stmt as stmts;
90pub use parser::types;