Maintainers
Pricing
Enterprise
More
More
Documentation
Try Live
Rankings
Install
Blog
Docs7
Ask
New
Add Docs
Chumsky
https://github.com/zesterer/chumsky
Admin
Write expressive, high-performance parsers with ease.
Tokens:
16,367
Snippets:
224
Trust Score:
9.8
License:
MIT
Update:
5 months ago
Context
Chat
Benchmark
66.56
Latest
Show doc for...
Code
Info
Show Results
Tokens:
Raw
Copy
Link
Tokens:
Raw
Copy
Link
### Example Program for Interpreter Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md A sample program demonstrating variable assignment, function definition, and function calls. ```plaintext let five = 5; let eight = 3 + five; fn add x y = x + y; add(five, eight) ``` -------------------------------- ### Foldl Input Example Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Illustrates the input structure provided to the `foldl` combinator for a chain of binary operations. ```text Num(2.0), [(Expr::Add, Num(3.0)), (Expr::Sub, Num(7.0)), (Add, Num(5.0))] ``` -------------------------------- ### Sample Foo Language Code Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md This is an example of code written in the 'Foo' programming language, which will be parsed and interpreted throughout the tutorial. ```text let seven = 7; fn add x y = x + y; add(2, 3) * -seven ``` -------------------------------- ### Example Parse Result for a Single Digit Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Shows the expected output format when parsing a single digit using the `Expr::Num` parser. ```rust ParseResult { output: Some(Num(5.0)), errs: [] } ``` -------------------------------- ### Example AST Encoding for 'let x = 5; x * 3' Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Demonstrates how the expression 'let x = 5; x * 3' is represented using the `Expr` enum. ```rust Expr::Let { name: "x", rhs: Box::new(Expr::Num(5.0)), then: Box::new(Expr::Mul( Box::new(Expr::Var("x")), Box::new(Expr::Num(3.0)) )), } ``` -------------------------------- ### Implement String Interner with HashMap Source: https://github.com/zesterer/chumsky/blob/main/guide/key_concepts.md This example demonstrates how to implement a simple string interner using a `HashMap` to manage shared state during parsing. It assigns unique IDs to identifiers and reuses IDs for repeated strings. Note that parser state operations are not guaranteed to be called a specific number of times. ```rust use chumsky::{prelude::*, inspector::SimpleState}; // A type alias that describes the extra type parameters of our parser (including the intern table). // `SimpleState` just represents a bog-standard ball of mutable state that does not care about input rewinding. type MyExtra = extra::Full<EmptyErr, SimpleState<HashMap<String, usize>>, ()>; // Our parser emits a vector of IDs. IDs correspond to identifiers, and can be quickly compared for equality fn my_parser<'a>() -> impl Parser<'a, &'a str, Vec<usize>, MyExtra> { text::ident() .map_with(|s: &str, e| { // Fetch our shared parser state let state: &mut SimpleState<HashMap<_, _>> = e.state(); // We use the size of the intern table to generate new IDs let id = state.len(); // If the string already exists in the table, find the old ID. Otherwise, insert a new ID. *state.entry(s.to_string()).or_insert(id) }) .padded() .repeated() .collect() } // Parse a list of identifiers. Some of them are repeated! let idents = my_parser().parse("the rabbit saw the other rabbit").into_result().unwrap(); // 'the' and 'rabbit' are not the same assert_ne!(idents[0], idents[1]); // But the two occurences of 'the' are the same... assert_eq!(idents[0], idents[3]); // ...as are the occurrences of 'rabbit' assert_eq!(idents[1], idents[5]); ``` -------------------------------- ### Define a Basic Parser Function with `impl Trait` Source: https://github.com/zesterer/chumsky/blob/main/guide/getting_started.md Create a parser function using `impl Trait` to let the compiler infer complex parser types. This example defines a parser that only accepts an empty input. ```rust # use chumsky::prelude::* fn parser<'src>() -> impl Parser<'src, &'src str, ()> { end() } ``` -------------------------------- ### Build and Test Documentation Source: https://github.com/zesterer/chumsky/blob/main/guide/README.md Use this command to build and test the documentation locally, ensuring changes render correctly. Appending `--open` will automatically open the built documentation in your web browser. ```bash RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features ``` -------------------------------- ### Test Naive Recovery Strategy Source: https://github.com/zesterer/chumsky/blob/main/guide/error_and_recovery.md Demonstrates the output of the lexer using the naive recovery strategy, showing generic `Unknown` errors for invalid input. ```rust assert_eq!( lexer().parse("[[💥, two], [💥, 4]]").output(), Some(&Expr::List(vec![ Expr::Error(ErrorKind::Unknown), Expr::Error(ErrorKind::Unknown) ])) ); ``` -------------------------------- ### Basic File Reading Program Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Reads the first command-line argument as a file path, reads its content, and prints it to the console. Uses `.unwrap()` for error handling, suitable for tutorials. ```rust use chumsky::prelude::*; fn main() { let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(); println!("{}", src); } ``` -------------------------------- ### Test a Simple Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/getting_started.md Demonstrates how to parse an empty string successfully and how to check for errors with non-empty strings using `Parser::parse` and `ParseResult::into_result`. ```rust # use chumsky::prelude::* # fn parser<'src>() -> impl Parser<'src, &'src str, ()> { end() } #[test] fn test_parser() { // Our parser expects empty strings, so this should parse successfully assert_eq!(parser().parse("").into_result(), Ok(())); // Anything other than an empty string should produce an error assert!(parser().parse("123").has_errors()); } ``` -------------------------------- ### Import Chumsky Prelude Source: https://github.com/zesterer/chumsky/blob/main/guide/getting_started.md Import all commonly used types, traits, and functions from Chumsky's prelude for convenience. ```rust use chumsky::prelude::*; ``` -------------------------------- ### Implement a Naive Recovery Strategy Source: https://github.com/zesterer/chumsky/blob/main/guide/error_and_recovery.md A naive recovery strategy that attempts to recover by matching a bracketed sequence, mapping to an `Unknown` error if successful. ```rust let naive_recovery = just('[') .then(none_of(']').repeated().then(just(']'))) .map(|_| ErrorKind::Unknown); ``` -------------------------------- ### Test variable shadowing Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md This program demonstrates variable shadowing. It should output 8, showing that the inner 'x' correctly shadows the outer 'x'. ```ignore let x = 5; let x = 3 + x; x ``` -------------------------------- ### Parse and Return Context Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `then_with_ctx()` to parse a pattern and utilize its output as context for another pattern, returning the context. Refer to `ConfigParser::configure` for information regarding context-sensitive parsing. ```rust a.then_with_ctx(b) ``` -------------------------------- ### Try Map Parser Output with Metadata Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `try_map_with` to apply a fallible mapping function to a parser's output, with access to output metadata. This enables context-aware fallible transformations. ```rust a.try_map_with(...) ``` -------------------------------- ### Foldl Operation Visualization Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md A visual representation of how `foldl` processes a chain of binary operations to build an expression tree. ```text Num(2.0), [(Add, Num(3.0)), (Sub, Num(7.0)), (Add, Num(5.0))]) -------- --------------- -------------- --------------- | | | | \ / | | Add(Num(2.0), Num(3.0)) | | | | | \ / Sub(Add(Num(2.0), Num(3.0)), Num(7.0)) | | | \ / Add(Sub(Add(Num(2.0), Num(3.0)), Num(7.0)), Num(5.0)) ``` -------------------------------- ### Use Input Slice as Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `to_slice` method parses a pattern and uses the corresponding input slice as the output. This requires inputs that implement `SliceInput`. ```rust a.to_slice() ``` -------------------------------- ### Test Specific Recovery Strategy Source: https://github.com/zesterer/chumsky/blob/main/guide/error_and_recovery.md Demonstrates the output of the lexer using the specific `text_recovery` strategy, extracting `UnexpectedText` errors. ```rust assert_eq!( lexer().parse("[[1, two], [three, 4]]").output(), Some(&Expr::List(vec![ Expr::List(vec![ Expr::Int(1), Expr::Error(ErrorKind::UnexpectedText(String::from("two"))) ]), Expr::List(vec![ Expr::Error(ErrorKind::UnexpectedText(String::from("three"))), Expr::Int(4) ]) ])) ); ``` -------------------------------- ### Use a placeholder parser with `todo` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `todo` parser acts as a placeholder and will panic if invoked during parsing. It is spiritually similar to the `todo!` macro. ```rust foo.then(todo()) ``` -------------------------------- ### Parsing and Printing AST in Main Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Modifies the main function to use the defined parser to parse the input source string and print the resulting AST. ```rust println!("{:?}", parser().parse(&src)); ``` -------------------------------- ### Main Function for Parsing and Evaluation Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Reads source code from a file, parses it into an AST, and then evaluates the AST. It handles and prints both parsing and evaluation errors. ```rust fn main() { let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(); match parser().parse(&src).into_result() { Ok(ast) => match eval(&ast) { Ok(output) => println!("{}", output), Err(eval_err) => println!("Evaluation error: {}", eval_err), }, Err(parse_errs) => parse_errs .into_iter() .for_each(|e| println!("Parse error: {}", e)), } } ``` -------------------------------- ### Combine Recovery Strategies with Parser Expressions Source: https://github.com/zesterer/chumsky/blob/main/guide/error_and_recovery.md Combines list parsing with specific `text_recovery` and a fallback `naive_recovery` strategy using `recover_with`. ```rust recursive(|expr| { expr.separated_by(just(',')) .collect::<Vec<_>>() .delimited_by(just('['), just(']')) .map(Expr::List) // If parsing a list expression fails, guess at the error being accidental text input. .recover_with(via_parser(text_recovery.map(Expr::Error))) .or(int) // Fallback to less conservative recovery otherwise. .recover_with(via_parser(naive_recovery.map(Expr::Error))) .padded() }) ``` -------------------------------- ### Implement a Specific Text Recovery Strategy Source: https://github.com/zesterer/chumsky/blob/main/guide/error_and_recovery.md This strategy recovers from errors by collecting consecutive ASCII alphabetic characters as an `UnexpectedText` error. ```rust let text_recovery = any() .filter(|c: &char| c.is_ascii_alphabetic()) .repeated() .at_least(1) .collect::<String>() .map(|s| ErrorKind::UnexpectedText(s)); ``` -------------------------------- ### Map Parser Output with Metadata Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `map_with` to transform the output of a parser, gaining access to associated metadata. This allows for more context-aware transformations. ```rust a.map_with(...) ``` -------------------------------- ### Parser::map_with Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Maps the output of a parser using a provided function, which also has access to metadata associated with the output. This allows for more context-aware transformations. ```APIDOC ## Parser::map_with ### Description Map the output of a parser using the given mapping function, with access to metadata associated with the output. ### Method `map_with(mapping_function_with_metadata)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.map_with(|output, metadata| /* transform output using metadata */) ``` ### Response #### Success Response (200) - The transformed output of the parser. ``` -------------------------------- ### Sequential Parsing with `then` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `then` to parse one pattern followed by another, returning a tuple of both results. Ensure both parsers succeed. ```rust a.then(b) ``` -------------------------------- ### Validate Parser Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `validate` to parse a pattern and then validate its success. This allows emitting secondary errors if the output does not meet certain criteria. ```rust a.validate(...) ``` -------------------------------- ### Recognize a specific token with `just` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `just` to recognize a specific token or an exact sequence of tokens. This is a fundamental primitive for matching exact patterns. ```rust just('a') ``` ```rust just("hello") ``` -------------------------------- ### Parse with Provided Context Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `with_ctx()` combinator parses a pattern using a specified context. For more information on context-sensitive parsing, see `ConfigParser::configure`. ```rust a.with_ctx(ctx) ``` -------------------------------- ### Try Map Parser Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `try_map` to apply a fallible mapping function to a parser's output. The parser fails if the mapping function returns an error. ```rust a.try_map(...) ``` -------------------------------- ### Evaluate Abstract Syntax Tree (AST) Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Recursively evaluates an AST representing arithmetic expressions. It handles number literals and basic arithmetic operations (addition, subtraction, multiplication, division). Runtime errors are propagated using the `?` operator. ```rust fn eval<'src>(expr: &'src Expr<'src>) -> Result<f64, String> { match expr { Expr::Num(x) => Ok(*x), Expr::Neg(a) => Ok(-eval(a)?), Expr::Add(a, b) => Ok(eval(a)? + eval(b)?), Expr::Sub(a, b) => Ok(eval(a)? - eval(b)?), Expr::Mul(a, b) => Ok(eval(a)? * eval(b)?), Expr::Div(a, b) => Ok(eval(a)? / eval(b)?), _ => todo!(), // We'll handle other cases later } } ``` -------------------------------- ### Define Integer and Atom Parsers Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Parses integers and assigns them to the `atom` parser. The integer parser is configured for base 10 and includes padding. ```rust let int = text::int(10) .map(|s: &str| Expr::Num(s.parse().unwrap())) .padded(); let atom = int; ``` -------------------------------- ### Recognize any token with `any` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `any` to recognize any single token, with the exception of the end of the input. It can be further filtered for specific conditions. ```rust any().filter(char::is_whitespace) ``` -------------------------------- ### Recover from Parsing Errors Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Employ `recover_with()` to attempt parsing a pattern. If it fails, a specified recovery strategy is used to handle the error. Refer to the documentation for detailed information on recovery strategies. ```rust a.recover_with(r) ``` -------------------------------- ### Foo Expression Language AST Definition Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Defines the Abstract Syntax Tree (AST) for the Foo expression language. Uses `Box` to handle recursive types and avoid infinite size. Supports numbers, variables, arithmetic operations, function calls, and let/fn bindings. ```rust #[derive(Debug)] enum Expr<'src> { Num(f64), Var(&'src str), Neg(Box<Expr<'src>>), Add(Box<Expr<'src>>, Box<Expr<'src>>), Sub(Box<Expr<'src>>, Box<Expr<'src>>), Mul(Box<Expr<'src>>, Box<Expr<'src>>), Div(Box<Expr<'src>>, Box<Expr<'src>>), Call(&'src str, Vec<Expr<'src>>), Let { name: &'src str, rhs: Box<Expr<'src>>, then: Box<Expr<'src>>, }, Fn { name: &'src str, args: Vec<&'src str>, body: Box<Expr<'src>>, then: Box<Expr<'src>>, } } ``` -------------------------------- ### Box a Parser for Heap Allocation Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `boxed()` to perform type-erasure on a parser, allocating it on the heap. This can improve compilation times and allows for dynamic parser construction at runtime. ```rust a.boxed() ``` -------------------------------- ### Ignore Contextual Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `ignore_with_ctx()` combinator parses a pattern and uses its output as context for another pattern, but it does not return the context itself. Consult `ConfigParser::configure` for details on context-sensitive parsing. ```rust a.ignore_with_ctx(b) ``` -------------------------------- ### Parse Binary Operators in Rust Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Defines parsers for integers, unary negation, and binary operations (multiplication, division, addition, subtraction) with correct precedence. Uses `foldl` to handle left-associative binary operations. ```rust let int = text::int(10) .map(|s: &str| Expr::Num(s.parse().unwrap())) .padded(); let atom = int; let op = |c| just(c).padded(); let unary = op('-') .repeated() .foldr(atom, |_op, rhs| Expr::Neg(Box::new(rhs))); let product = unary.foldl( choice(( op('*').to(Expr::Mul as fn(_, _) -> _), op('/').to(Expr::Div as fn(_, _) -> _), )) .then(unary) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); let sum = product.foldl( choice(( op('+').to(Expr::Add as fn(_, _) -> _), op('-').to(Expr::Sub as fn(_, _) -> _), )) .then(product) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); sum ``` -------------------------------- ### Rust Factorial Function Source: https://github.com/zesterer/chumsky/blob/main/guide/recursion.md A standard recursive implementation of the factorial function in Rust. This serves as a baseline for understanding recursion. ```rust fn factorial(x: u32) -> u32 { if x <= 1 { 1 } else { x * factorial(x - 1) } } ``` -------------------------------- ### Pad Text-like Input Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `padded` to skip whitespace on either side of a pattern. This combinator is specifically for text-like inputs (e.g., `u8` or `char` tokens). ```rust a.padded() ``` -------------------------------- ### Recognize no input with `empty` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `empty` to recognize no input. This parser always succeeds without advancing the input, making it useful for creating alternative parsing paths or zero-width assertions. ```rust empty().then(y) ``` -------------------------------- ### Alternative Parsing with `or` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `or` to attempt parsing one pattern, falling back to another if the first fails. Useful for implementing branching logic. ```rust a.or(b) ``` -------------------------------- ### Filter Parser Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `filter` to parse a pattern and apply a filtering function to its output. The parser fails if the filter function returns `false`. ```rust any().filter(char::is_lowercase) ``` -------------------------------- ### Evaluate Expressions with Variables and Let Bindings in Rust Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Evaluates abstract syntax tree nodes, handling numbers, negation, arithmetic operations, variable lookups, and let bindings. Manages variable scope using a vector of (name, value) pairs. ```rust fn eval<'src>(expr: &'src Expr<'src>, vars: &mut Vec<(&'src str, f64)>) -> Result<f64, String> { match expr { Expr::Num(x) => Ok(*x), Expr::Neg(a) => Ok(-eval(a, vars)?), Expr::Add(a, b) => Ok(eval(a, vars)? + eval(b, vars)?), Expr::Sub(a, b) => Ok(eval(a, vars)? - eval(b, vars)?), Expr::Mul(a, b) => Ok(eval(a, vars)? * eval(b, vars)?), Expr::Div(a, b) => Ok(eval(a, vars)? / eval(b, vars)?), Expr::Var(name) => { if let Some((_, val)) = vars.iter().rev().find(|(var, _)| var == name) { Ok(*val) } else { Err(format!("Cannot find variable `{}` in scope", name)) } } Expr::Let { name, rhs, then } => { let rhs = eval(rhs, vars)?; vars.push((name, rhs)); let output = eval(then, vars); vars.pop(); output } _ => todo!(), } } ``` -------------------------------- ### Map Parser Output with a Function Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `map` to transform the output of a parser using a provided function. This is useful for changing the type or structure of the parsed data. ```rust a.map(...) ``` -------------------------------- ### Map Parser Error with Metadata Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `map_err_with` to map parser errors while having access to output metadata. This allows for more context-aware error transformations. ```rust a.map_err_with(...) ``` -------------------------------- ### Parsing a Single Digit Character Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Uses `any()` to accept any character and `filter()` to ensure it's an ASCII digit. This is a basic primitive parser. ```rust any() .filter(|c: &char| c.is_ascii_digit()) ``` -------------------------------- ### Rust Brainfuck Parser with Chumsky Source: https://github.com/zesterer/chumsky/blob/main/README.md This Rust code defines a parser for the Brainfuck programming language using the Chumsky library. It handles basic instructions and nested loops, generating an Abstract Syntax Tree (AST). ```rust use chumsky::prelude::*; /// An AST (Abstract Syntax Tree) for Brainfuck instructions #[derive(Clone)] enum Instr { Left, Right, Incr, Decr, Read, Write, Loop(Vec<Self>), // In Brainfuck, `[...]` loop instructions contain any number of instructions } /// A function that generates a Brainfuck parser fn brainfuck<'a>() -> impl Parser<'a, &'a str, Vec<Instr>> { // Brainfuck syntax is recursive: each instruction can contain many sub-instructions (via `[...]` loops) recursive(|bf| choice(( // All of the basic instructions are just single characters just('<').to(Instr::Left), just('>').to(Instr::Right), just('+').to(Instr::Incr), just('-').to(Instr::Decr), just(',').to(Instr::Read), just('.').to(Instr::Write), // Loops are strings of Brainfuck instructions, delimited by square brackets bf.delimited_by(just('['), just(']')).map(Instr::Loop), )) // Brainfuck instructions appear sequentially, so parse as many as we need .repeated() .collect()) } // Parse some Brainfuck with our parser brainfuck().parse("--[>--->->->++>-<<<<<-------]>--.>---------.>--..+++.>----.>+++++++++.<<.+++.------.<-.>>+.") ``` -------------------------------- ### Parser::to_slice Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Parses a pattern and uses a slice of the input corresponding to that pattern as the output, discarding the original parsed output. Requires inputs that implement `SliceInput`. ```APIDOC ## Parser::to_slice ### Description Parse a pattern. Discard the output of the pattern and instead use a slice of the input that the pattern corresponds to as the output. Requires inputs that implement [`SliceInput`]. ### Method `to_slice()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.to_slice() ``` ### Response #### Success Response (200) - A slice of the input that the pattern corresponds to. ``` -------------------------------- ### Add Chumsky Dependency in Cargo.toml Source: https://github.com/zesterer/chumsky/blob/main/guide/getting_started.md Manually add Chumsky to your project's `Cargo.toml` file to manage dependencies. ```toml chumsky = "0.10" ``` -------------------------------- ### Parse String to Type with FromStr Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `from_str` to parse a string output from a parser and then convert it into another type using Rust's `FromStr` trait. Often paired with `unwrapped` to handle potential parsing errors. ```rust just("true").from_str().unwrapped() ``` -------------------------------- ### Recursive Parser using `recursive` Combinator Source: https://github.com/zesterer/chumsky/blob/main/guide/recursion.md A correct implementation of a recursive parser using Chumsky's `recursive` combinator. This avoids compilation errors by passing the parser definition via a closure. ```rust use chumsky::prelude::*; fn a_parser<'src>() -> impl Parser<'src, &'src str, i32> { recursive(|a_parser| { let int = text::int(10).map(|s: &str| s.parse().unwrap()); let atom = choice(( int, a_parser.delimited_by(just('('), just(')')), )) .padded(); atom.clone().foldl( just('+').padded().ignore_then(atom).repeated(), |lhs, rhs| lhs + rhs, ) }) } ``` -------------------------------- ### Define Let Declaration Parser in Rust Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Parses 'let' declarations, binding an identifier to an expression and then continuing with further declarations or expressions. Uses `ignore_then` and `then_ignore` to omit syntax elements. ```rust let decl = recursive(|decl| { let r#let = text::ascii::keyword("let") .ignore_then(ident) .then_ignore(just('=')) .then(expr.clone()) .then_ignore(just(';')) .then(decl) .map(|((name, rhs), then)| Expr::Let { name, rhs: Box::new(rhs), then: Box::new(then), }); r#let // Must be later in the chain than `r#let` to avoid ambiguity .or(expr) .padded() }); ``` -------------------------------- ### Define Function Declaration Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Extends the parser to recognize function declarations, similar to let bindings. Uses `repeated()` to capture arguments and `collect()` to gather them into a vector. ```rust let decl = recursive(|decl| { let r#let = text::ascii::keyword("let") .ignore_then(ident) .then_ignore(just('=')) .then(expr.clone()) .then_ignore(just(';')) .then(decl.clone()) .map(|((name, rhs), then)| Expr::Let { name, rhs: Box::new(rhs), then: Box::new(then), }); let r#fn = text::ascii::keyword("fn") .ignore_then(ident) .then(ident.repeated().collect::<Vec<_>>()) .then_ignore(just('=')) .then(expr.clone()) .then_ignore(just(';')) .then(decl) .map(|(((name, args), body), then)| Expr::Fn { name, args, body: Box::new(body), then: Box::new(then), }); r#let.or(r#fn).or(expr).padded() }); ``` -------------------------------- ### Use Constant Value as Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `to` combinator parses a pattern but ignores its output, using a specified constant value as the result instead. ```rust a.to(x) ``` -------------------------------- ### Filter Map Parser Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `filter_map` to parse a pattern and apply a filter-map function to its output. The parser fails if the function returns `None`. ```rust any().filter_map(...) ``` -------------------------------- ### Parser::to Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Parses a pattern, ignores its output, and uses a specified constant value as the output instead. This is useful for simplifying parser chains where the intermediate result is not needed. ```APIDOC ## Parser::to ### Description Parse a pattern, ignoring the output value and using a constant value as the output value instead. ### Method `to(constant_value)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.to(some_value) ``` ### Response #### Success Response (200) - The specified constant value. ``` -------------------------------- ### Left-Fold Accumulation with `foldl` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `foldl` to parse a pattern and then iteratively apply another parser, accumulating the results using a provided function. Often used for binary operators. ```rust a.foldl(b.repeated(), ...) ``` -------------------------------- ### Rewind Input After Parsing Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `rewind()` to parse a pattern and then reset the input stream to the beginning of that pattern upon success. This is often used when a pattern is expected to be followed by other content. ```rust a.then(b.rewind()) ``` -------------------------------- ### Parse with Negative Lookahead Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `not()` within `and_is()` to reject input that matches a given pattern without consuming any input on success. This is useful for asserting the absence of a pattern. ```rust a.and_is(b.not()) ``` -------------------------------- ### Try Fold Left Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `try_foldl` to perform a left-fold operation on parser outputs, allowing for fallible reductions. If the folding function returns an error, the parser fails. ```rust a.try_foldl(...) ``` -------------------------------- ### Define Function Call Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Adds a parser for function calls, handling argument lists. Uses `separated_by` to parse comma-separated arguments and `allow_trailing` to permit trailing commas. ```rust let call = ident .then( expr.clone() .separated_by(just(',')) .allow_trailing() // Foo is Rust-like, so allow trailing commas to appear in arg lists .collect::<Vec<_>>() .delimited_by(just('('), just(')')), ) .map(|(f, args)| Expr::Call(f, args)); let atom = int .or(expr.delimited_by(just('('), just(')'))) .or(call) .or(ident.map(Expr::Var)) .padded(); ``` -------------------------------- ### Parse Multi-Digit Integer with `text::int` Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Parses a multi-digit integer using the `text::int(10)` primitive and maps the resulting string slice to a floating-point number. `padded()` is a shortcut for ignoring leading/trailing whitespace. ```rust text::int(10) .map(|s: &str| Expr::Num(s.parse().unwrap())) .padded() ``` -------------------------------- ### Define Operator Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Creates a reusable parser for a single character operator, including padding. ```rust let op = |c| just(c).padded(); ``` -------------------------------- ### Parse with Positive Lookahead Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `and_is()` combinator parses one pattern only if another parser also successfully parses at the same input location. It asserts the presence of the second pattern without consuming input. ```rust a.and_is(b) ``` -------------------------------- ### Naive Recursive Parser (Compilation Error) Source: https://github.com/zesterer/chumsky/blob/main/guide/recursion.md An attempt to define a recursive parser using a direct function call, which results in a compilation error due to recursive opaque types. This approach should be avoided. ```rust use chumsky::prelude::*; fn a_parser<'src>() -> impl Parser<'src, &'src str, i32> + Clone { let int = text::int(10).map(|s: &str| s.parse().unwrap()); let atom = choice(( int, a_parser().delimited_by(just('('), just(')')), )) .padded(); atom.clone().foldl( just('+').padded().ignore_then(atom).repeated(), |lhs, rhs| lhs + rhs, ) } ``` -------------------------------- ### Repeated Parsing with `repeated` and `collect` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `repeated` to parse a pattern zero or more times. Combine with `collect` to gather all parsed results into a collection like `Vec`. ```rust a.repeated().collect::<Vec<_>>() ``` -------------------------------- ### Parser::ignored Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Parses a pattern, ignores its output, and uses the unit type `()` as the output. This is a convenient shorthand for `to(())`. ```APIDOC ## Parser::ignored ### Description Parse a pattern, ignoring the output value and using `()` as the output value instead. ### Method `ignored()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.ignored() ``` ### Response #### Success Response (200) - The unit type `()`. ``` -------------------------------- ### Recognize any token within a sequence with `one_of` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `one_of` to recognize any single token that is part of a given sequence. This is useful for matching against a set of possible characters or tokens. ```rust one_of('0'..='9') ``` ```rust one_of("<>") ``` -------------------------------- ### Parser::unwrapped Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Parses a pattern that returns a `Result` or `Option`, and then unwraps the contained value. This simplifies handling of parsers that may fail or return optional values. ```APIDOC ## Parser::unwrapped ### Description Parse a pattern that returns either a [`Result`] or an [`Option`], then unwrap them. ### Method `unwrapped()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.unwrapped() ``` ### Response #### Success Response (200) - The unwrapped value from the `Result` or `Option`. ``` -------------------------------- ### Optional Parsing with `or_not` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `or_not` to attempt parsing a pattern, returning `Some(result)` on success or `None` on failure. This allows for optional patterns. ```rust a.or_not() ``` -------------------------------- ### Recursive Parser for Expressions with Parentheses Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Defines a recursive parser for arithmetic expressions that supports nested parentheses, unary minus, multiplication, division, addition, and subtraction. Use this when you need to parse complex expressions with varying operator precedence. ```rust recursive(|expr| { let int = text::int(10).map(|s: &str| Expr::Num(s.parse().unwrap())); let atom = int.or(expr.delimited_by(just('('), just(')'))).padded(); let op = |c| just(c).padded(); let unary = op('-') .repeated() .foldr(atom, |_op, rhs| Expr::Neg(Box::new(rhs))); let product = unary.clone().foldl( choice(( op('*').to(Expr::Mul as fn(_, _) -> _), op('/').to(Expr::Div as fn(_, _) -> _), )) .then(unary) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); let sum = product.clone().foldl( choice(( op('+').to(Expr::Add as fn(_, _) -> _), op('-').to(Expr::Sub as fn(_, _) -> _), )) .then(product) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); sum }) ``` -------------------------------- ### Collect Iterated Elements into Exact-Sized Array Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `collect_exactly` to gather elements from an `IterParser` into an exact-sized array type that implements `ContainerExactly`. The size `N` must be known at compile time. ```rust a.repeated().collect_exactly::<[_; N]>() ``` -------------------------------- ### Define Expression Parsers in Rust Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Defines parsers for integers, variables, and arithmetic operations with correct precedence. Uses recursive parsers for handling nested expressions and operator chaining. ```rust let ident = text::ascii::ident().padded(); let expr = recursive(|expr| { let int = text::int(10).map(|s: &str| Expr::Num(s.parse().unwrap())); let atom = int .or(expr.delimited_by(just('('), just(')'))) .or(ident.map(Expr::Var)) .padded(); let op = |c| just(c).padded(); let unary = op('-') .repeated() .foldr(atom, |_op, rhs| Expr::Neg(Box::new(rhs))); let product = unary.clone().foldl( choice(( op('*').to(Expr::Mul as fn(_, _) -> _), op('/').to(Expr::Div as fn(_, _) -> _), )) .then(unary) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); let sum = product.clone().foldl( choice(( op('+').to(Expr::Add as fn(_, _) -> _), op('-').to(Expr::Sub as fn(_, _) -> _), )) .then(product) .repeated(), |lhs, (op, rhs)| op(Box::new(lhs), Box::new(rhs)), ); sum }); ``` -------------------------------- ### Parse Number with Whitespace Handling Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Parses a single digit and maps it to a floating-point number. It uses `padded_by` to ignore any leading or trailing whitespace characters. ```rust any() .filter(|c: &char| c.is_ascii_digit()) .map(|c| Expr::Num(c.to_digit(10).unwrap() as f64)) .padded_by(any().filter(|c: &char| c.is_whitespace()).repeated()) ``` -------------------------------- ### Recognize the end of input with `end` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `end` to recognize only the end of the input. This parser does not consume any input and succeeds only when the input is fully consumed. ```rust x.then(end()) ``` -------------------------------- ### Parser::map Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Maps the output of a parser using a provided function. This is useful for transforming the parsed data into a different type or format. ```APIDOC ## Parser::map ### Description Map the output of a parser using the given mapping function. ### Method `map(mapping_function)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.map(|output| /* transform output */) ``` ### Response #### Success Response (200) - The transformed output of the parser. ``` -------------------------------- ### Map Parser Error with State Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `map_err_with_state` to map parser errors with access to the parser's state. This is beneficial when error handling depends on the parser's execution context. ```rust a.map_err_with_state(...) ``` -------------------------------- ### Add Chumsky Dependency via Cargo CLI Source: https://github.com/zesterer/chumsky/blob/main/guide/getting_started.md Use this command to add Chumsky to your project's dependencies using the Cargo CLI. ```sh $ cargo add chumsky ``` -------------------------------- ### Ignore Parser Output Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `ignored` to parse a pattern and replace its output with the unit type `()`. This is useful when only the success of a parse is important, not its value. ```rust a.ignored() ``` -------------------------------- ### Modify Eval Call in Main Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Update the `eval` call in `main` to include function and variable stacks. ```rust eval(&ast, &mut Vec::new(), &mut Vec::new()) ``` -------------------------------- ### Make Top-Level Parsers Lazy Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Apply `lazy()` to top-level parsers to ensure they only recognize as much input as they can and no more. This combinator is primarily useful for controlling input consumption at the highest level of parsing. ```rust a.lazy() ``` -------------------------------- ### Ignoring First Result with `ignore_then` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `ignore_then` to parse two patterns sequentially, but only keep the result of the second. The first parser's output is discarded. ```rust a.ignore_then(b) ``` -------------------------------- ### Label Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `labelled` to assign a name to a parser. This name is used in error reporting to provide more context about parsing failures. ```rust a.labelled("a") ``` -------------------------------- ### Implement Function Evaluation Logic Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Extends the `eval` function to handle function calls and declarations. Manages a function stack and variable scope for function execution. ```rust fn eval<'src>( expr: &'src Expr<'src>, vars: &mut Vec<(&'src str, f64)>, funcs: &mut Vec<(&'src str, &'src [&'src str], &'src Expr<'src>)>, // Function stack ) -> Result<f64, String> { match expr { Expr::Num(x) => Ok(*x), Expr::Neg(a) => Ok(-eval(a, vars, funcs)?), Expr::Add(a, b) => Ok(eval(a, vars, funcs)? + eval(b, vars, funcs)?), Expr::Sub(a, b) => Ok(eval(a, vars, funcs)? - eval(b, vars, funcs)?), Expr::Mul(a, b) => Ok(eval(a, vars, funcs)? * eval(b, vars, funcs)?), Expr::Div(a, b) => Ok(eval(a, vars, funcs)? / eval(b, vars, funcs)?), Expr::Var(name) => { if let Some((_, val)) = vars.iter().rev().find(|(var, _)| var == name) { Ok(*val) } else { Err(format!("Cannot find variable `{}` in scope", name)) } } Expr::Let { name, rhs, then } => { let rhs = eval(rhs, vars, funcs)?; vars.push((*name, rhs)); let output = eval(then, vars, funcs); vars.pop(); output } Expr::Call(name, args) => { if let Some((_, arg_names, body)) = funcs.iter().rev().find(|(var, _, _)| var == name).copied() { if arg_names.len() == args.len() { let mut args = args .iter() .map(|arg| eval(arg, vars, funcs)) .zip(arg_names.iter()) .map(|(val, name)| Ok((*name, val?))) .collect::<Result<_, String>>()?; let old_vars = vars.len(); vars.append(&mut args); let output = eval(body, vars, funcs); vars.truncate(old_vars); output } else { Err(format!( "Wrong number of arguments for function `{}`: expected {}, found {}", name, arg_names.len(), args.len(), )) } } else { Err(format!("Cannot find function `{}` in scope", name)) } } Expr::Fn { name, args, body, then, } => { funcs.push((name, args, body)); let output = eval(then, vars, funcs); funcs.pop(); output } } } ``` -------------------------------- ### Memoize Parser Results Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Utilize `memoized()` to parse a pattern and store its success or failure. This stored information is reused when parsing the same input again, enabling the expression of left-recursive or exponential patterns. ```rust a.memoized() ``` -------------------------------- ### Recognize any token not in a sequence with `none_of` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `none_of` to recognize any single token that is not part of a given sequence. This is useful for parsing until a specific delimiter is found. ```rust none_of(';') ``` ```rust none_of("xyz") ``` -------------------------------- ### IterParser::collect_exactly Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Collects elements from an `IterParser` into an exact-sized container type that implements `ContainerExactly`. Useful for collecting into arrays. ```APIDOC ## IterParser::collect_exactly ### Description Collects elements of an [`IterParser`] into an exact-sized type implementing [`ContainerExactly`]. ### Method `collect_exactly::<ExactContainerType>()` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```rust parser.repeated().collect_exactly::<[_; N]>() ``` ### Response #### Success Response (200) - An exact-sized container (e.g., an array) holding the collected elements. ``` -------------------------------- ### Ignoring Second Result with `then_ignore` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `then_ignore` to parse two patterns sequentially, keeping only the result of the first. The second parser's output is discarded. ```rust a.then_ignore(b) ``` -------------------------------- ### Count Iterated Parser Elements Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `count` method returns the number of elements produced by an `IterParser`. This is useful for determining how many times a pattern repeated. ```rust a.repeated().count() ``` -------------------------------- ### Mapping a Digit Character to an AST Number Node Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Combines `filter` with `map` to convert a parsed digit character into an `Expr::Num` variant. The `unwrap()` is safe because `map` is only called on successful parses. ```rust any() .filter(|c: &char| c.is_ascii_digit()) .map(|c| Expr::Num(c.to_digit(10).unwrap() as f64)) ``` -------------------------------- ### Parse Unary Negation Operator Source: https://github.com/zesterer/chumsky/blob/main/guide/tutorial.md Parses zero or more negation operators followed by an atom, folding the results into a single `Expr::Neg` expression. ```rust let unary = op('-') .repeated() .foldr(atom, |_op, rhs| Expr::Neg(Box::new(rhs))); unary ``` -------------------------------- ### Parsing Separated Lists with `separated_by` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `separated_by` to parse a pattern multiple times, with a separator pattern interspersed between each occurrence. Useful for comma-separated lists. ```rust a.separated_by(b).count() ``` -------------------------------- ### Right-Fold Accumulation with `foldr` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `foldr` on an `IterParser` to parse elements, followed by a second pattern, and then fold the elements into the second parser's output. Useful for unary operators. ```rust a.repeated().foldr(b, ...) ``` -------------------------------- ### Unwrap Result or Option from Parser Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md The `unwrapped` combinator is used on parsers that yield a `Result` or `Option`. It automatically unwraps the successful value, propagating errors or `None`. ```rust a.unwrapped() ``` -------------------------------- ### Parsing Patterns Padded by Another with `padded_by` Source: https://github.com/zesterer/chumsky/blob/main/guide/meet_the_parsers.md Use `padded_by` to parse a pattern that is surrounded by another pattern on both sides. Useful for consuming whitespace or delimiters. ```rust a.padded_by(b) ```