Skip to main content

aver/parser/
mod.rs

1use std::sync::Arc as Rc;
2
3use crate::ast::*;
4use crate::lexer::{Token, TokenKind};
5use thiserror::Error;
6
7#[derive(Debug, Error)]
8pub enum ParseError {
9    #[error("error[{line}:{col}]: {msg}")]
10    Error {
11        msg: String,
12        line: usize,
13        col: usize,
14    },
15}
16
17pub struct Parser {
18    tokens: Vec<Token>,
19    pos: usize,
20    /// Iron — B4: monotonically-increasing recursion counter, guarded
21    /// against by `enter_recursion`. Without this the parser unwinds
22    /// its stack on inputs the fuzz harness routinely produces:
23    /// 2500+ nested `(...)`, `Option.Some(...)`, or `{...}` literals
24    /// reach the thread's default 8 MiB stack and abort with
25    /// `fatal runtime error: stack overflow` — a SIGSEGV that
26    /// `panic::catch_unwind` cannot recover from, taking the whole
27    /// `aver` invocation down. The cap below trades the theoretical
28    /// "what if someone really wants 1000-deep expression?" against
29    /// the practical "no human writes a 1000-deep expression and
30    /// fuzz keeps finding them".
31    recursion_depth: u32,
32}
33
34/// Iron — B4: hard cap on parser recursion depth. 128 is comfortably
35/// above any hand-written Aver shape (the deepest production
36/// expression in the corpus measures ~12 levels) and comfortably
37/// below the threshold where the parser starts unwinding the test
38/// runner's 2 MiB thread stack on the next nested `(`. The
39/// trade-off is intentional — users hit the typed error long
40/// before the runtime hits SIGSEGV, and the 2 MiB worker stack
41/// `cargo test` allocates per thread is the binding constraint,
42/// not the 8 MiB main-thread default in standalone CLI runs.
43pub(super) const MAX_PARSE_DEPTH: u32 = 64;
44
45mod blocks;
46mod core;
47mod expr;
48mod functions;
49mod module;
50mod patterns;
51mod types;