### Quick Start Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/api-reference.md Demonstrates the basic usage of the peg::parser! macro to define a grammar and parse a string. ```rust peg::parser!{ grammar list_parser() for str { rule number() -> u32 = n:$(['0'..='9']+) {? n.parse().or(Err("u32")) } pub rule list() -> Vec = "[" l:(number() ** ",") "]" { l } } } fn main() { // Call the generated function let result = list_parser::list("[1,2,3]"); assert_eq!(result, Ok(vec![1, 2, 3])); } ``` -------------------------------- ### Feature Flags Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Example of how to enable or disable features for the peg crate in Cargo.toml. ```toml # Enable peg = { version = "0.8", features = ["trace"] } # Disable std (requires alloc) peg = { version = "0.8", default-features = false } ``` -------------------------------- ### Simple Expression Parser Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md A basic example demonstrating a simple expression parser for addition. ```rust peg::parser! { grammar calc() for str { rule number() -> i64 = n:$(['0'..='9']+) { n.parse().unwrap() } pub rule expr() -> i64 = a:number() "+" b:number() { a + b } } } assert_eq!(calc::expr("2+3"), Ok(5)); ``` -------------------------------- ### Operator Precedence Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Demonstrates how to define operator precedence using the `precedence!{}` macro in rust-peg. ```rust peg::parser! { grammar ops() for str { rule _() = [' ']* rule number() -> i64 = n:$(['0'..='9']+) { n.parse().unwrap() } pub rule expr() -> i64 = precedence!{ x:(@) "+" y:@ { x + y } x:(@) "-" y:@ { x - y } -- x:(@) "*" y:@ { x * y } x:(@) "/" y:@ { x / y } -- x:@ "^" y:(@) { x.pow(y as u32) } "-" v:@ { -v } v:@ "!" { (1..=v).product() } -- "(" e:expr() ")" { e } n:number() { n } } } } #[test] fn test() { assert_eq!(ops::expr("2+3*4"), Ok(14)); // 2+(3*4) assert_eq!(ops::expr("2^3^2"), Ok(512)); // 2^(3^2), right-assoc assert_eq!(ops::expr("-2!"), Ok(-2)); // -(2!) assert_eq!(ops::expr("5!"), Ok(120)); // 5! } ``` -------------------------------- ### Query Language Parser Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md An example of a PEG grammar for a simple query language, demonstrating how to define rules for fields, values, operators, conditions, and expressions. ```rust peg::parser! { grammar query() for str { rule _() = [' ']* rule field() -> String = s:$(['a'..='z']+) { s.to_string() } rule value() -> String = "" s:$([^'"']*) "" { s.to_string() } rule op() -> &'static str = "=" / "!=" / ">" / "<" rule condition() -> (String, &'static str, String) = f:field() _ op:op() _ v:value() { (f, op, v) } rule expr() -> Vec<(String, &'static str, String)> = conditions:(condition() ++ ("AND" / "OR")) { conditions } pub rule parse() -> Vec<(String, &'static str, String)> = _ e:expr() _ { e } } } ``` -------------------------------- ### Custom Input Type Minimal Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Provides a minimal example of implementing the peg::Parse trait for a custom input type. ```rust use peg::{Parse, ParseElem, ParseLiteral, ParseSlice, RuleResult}; struct Tokens { /* ... */ } impl Parse for Tokens { type PositionRepr = usize; fn start(&self) -> usize { 0 } fn is_eof(&self, p: usize) -> bool { p >= self.tokens.len() } fn position_repr(&self, p: usize) -> usize { p } } impl<'input> ParseElem<'input> for Tokens { type Element = Token; fn parse_elem(&'input self, pos: usize) -> RuleResult { self.tokens.get(pos) .map(|t| RuleResult::Matched(pos + 1, t)) .unwrap_or(RuleResult::Failed) } } impl ParseLiteral for Tokens { fn parse_string_literal(&self, _pos: usize, _literal: &str) -> RuleResult<()> { RuleResult::Failed // Not applicable for token streams } } impl<'input> ParseSlice<'input> for Tokens { type Slice = &'input [Token]; fn parse_slice(&'input self, p1: usize, p2: usize) -> &'input [Token] { &self.tokens[p1..p2] } } peg::parser! { grammar p() for Tokens { pub rule parse() = ... } } ``` -------------------------------- ### Error Context Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Shows how to build custom error information by implementing `From` for a custom error struct. ```rust #[derive(Debug)] pub struct ParseError { pub message: String, pub line: usize, pub column: usize, pub expected: String, } impl From> for ParseError { fn from(err: peg::ParseError) -> Self { ParseError { message: "unexpected character".to_string(), line: err.location.line, column: err.location.column, expected: err.expected.to_string(), } } } peg::parser! { grammar lang() for str { pub rule keyword() -> String = s:$(['a'..='z']+) { s.to_string() } } } fn parse_keyword(input: &str) -> Result { lang::keyword(input).map_err(|e| e.into()) } ``` -------------------------------- ### Rule with Where Clause Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example demonstrating a rule with a 'where' clause to specify generic parameter bounds. ```rust rule foo(x: T) -> T where T::Err: std::fmt::Debug = "x" { x } ``` -------------------------------- ### Use Statement Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example demonstrating how to use Rust 'use' statements within the grammar body to import items into the grammar's scope. ```rust peg::parser! { grammar foo() for str { use std::str::FromStr; rule number() -> i32 = ... } } ``` -------------------------------- ### Track Source Locations Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example showing how to inject source code spans (start and end positions) into parsed results. ```rust inject span(_, start, end) -> Range { start..end } rule expr() -> (Value, Range) = v:value() { (v, span) } ``` -------------------------------- ### Value Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Example of a rule with value parameters. ```rust rule between(n: usize, m: usize) = e *<{n},{m}> ``` -------------------------------- ### ExpectedSet tokens method example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Example of iterating over the expected tokens in an ExpectedSet. ```rust for token in error.expected.tokens() { eprintln!("Expected token: {}", token); } ``` -------------------------------- ### Rule Usage Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example showing how to call the 'list' rule with the 'num_radix' rule as a PEG expression fragment parameter. ```rust pub rule parse() = list() ``` -------------------------------- ### Left Recursion Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md Example illustrating how to handle left recursion in grammars, with caching. ```rust peg::parser! { grammar expr() for str { rule number() -> i64 = n:$(['0'..='9']+) { n.parse().unwrap() } #[cache_left_rec] rule e() -> i64 = e:e() "+" n:number() { e + n } / number() pub rule parse() -> i64 = e() } } assert_eq!(expr::parse("1+2+3"), Ok(6)); ``` -------------------------------- ### ParseError Display implementation example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Example of how to handle a ParseError and display its location and expected tokens. ```rust use peg::ParseError; match list_parser::list("[not_a_number]") { Ok(result) => println!("{:?}", result), Err(err) => { println!("Parse failed at {}", err.location); println!("Expected: {}", err.expected); } } ``` -------------------------------- ### LineCol Display implementation example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Example of using LineCol to display error location. ```rust let err = parser::rule("input").unwrap_err(); println!("Error at {}:{}", err.location.line, err.location.column); ``` -------------------------------- ### Result Type Mapping Examples Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Examples showing how the Result type maps to different input types. ```rust // For grammar with input type `str` type ParseResult = Result>; // For grammar with input type `[u8]` type ParseResult = Result>; ``` -------------------------------- ### Simple Expression Parser Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md A basic arithmetic calculator supporting addition and multiplication. ```rust peg::parser! { grammar calc() for str { rule _() = [\' \' | \'\t\']* rule number() -> i64 = n:$(['0'..=\'9\']+) _ { n.parse().unwrap() } rule factor() -> i64 = n:number() { n } / "(" _ v:expr() _ ")" { v } rule term() -> i64 = a:factor() (mul:$("*" ) _ b:factor() { a * b })* rule expr() -> i64 = a:term() (add:$("+") _ b:term() { a + b })* pub rule parse() -> i64 = _ v:expr() _ ![_] { v } } } #[test] fn test_calc() { assert_eq!(calc::parse("2 + 3 * 4"), Ok(14)); assert_eq!(calc::parse("(2 + 3) * 4"), Ok(20)); assert_eq!(calc::parse("10"), Ok(10)); } ``` -------------------------------- ### Parameterized Rules Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Demonstrates how to use rules as parameters to create reusable parsers for lists with different separators. ```rust peg::parser! { grammar lists() for str { rule _() = [' ']* rule number() -> i32 = n:$(['0'..='9']+) _ { n.parse().unwrap() } rule sep_list(item: rule, sep: rule<()>) -> Vec = items:(item() ** (sep())) { items } rule comma() = "," _ rule semicolon() = ";" _ rule pipe() = "|" _ pub rule numbers() -> Vec = sep_list(, ) pub rule codes() -> Vec = sep_list(, ) pub rule flags() -> Vec = sep_list(, ) } } #[test] fn test() { assert_eq!(lists::numbers("1, 2, 3"), Ok(vec![1, 2, 3])); assert_eq!(lists::codes("1; 2; 3"), Ok(vec![1, 2, 3])); } ``` -------------------------------- ### Programming Language Grammar Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md A mini parser for a simple language. ```rust #[derive(Debug, Clone)] pub enum Expr { Int(i64), Var(String), Add(Box, Box), Call(String, Vec), } #[derive(Debug)] pub enum Stmt { Let(String, Expr), If(Expr, Vec, Vec), Return(Expr), } peg::parser! { grammar lang() for str { rule _() = quiet!{[' ' | '\t' | '\n']*} rule keyword(s: &'static str) -> &'static str = s:$([s.chars().next().unwrap()][s[1..].chars()]*) _ {? if s == s { Ok(s) } else { Err(s) } } rule ident() -> String = s:$(['a'..='z' | 'A'..='Z' | '_']['a'..='z' | 'A'..='Z' | '0'..='9' | '_']*) _ { s.to_string() } rule integer() -> i64 = n:$(['0'..=\'9\']+) _ { n.parse().unwrap() } rule expr() -> Expr = term() rule term() -> Expr = a:factor() (op:"+" _ b:factor() { Expr::Add(Box::new(a), Box::new(b)) })* rule factor() -> Expr = "(" _ e:expr() _ ")" { e } / name:ident() "(" args:(expr() ** ("," _)) ")" { Expr::Call(name, args) } / name:ident() { Expr::Var(name) } / n:integer() { Expr::Int(n) } rule statement() -> Stmt = "let" _ name:ident() "=" _ value:expr() _ ";" { Stmt::Let(name, value) } / "if" _ cond:expr() _ "{" stmts:statement()* "}" _ ("else" _ "{" else_stmts:statement()* "}")? { Stmt::If(cond, stmts, else_stmts.unwrap_or_default()) } / "return" _ value:expr() _ ";" { Stmt::Return(value) } pub rule program() -> Vec = _ stmts:statement()* _ { stmts } } } ``` -------------------------------- ### CSV Parser Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Parse comma-separated values. ```rust peg::parser! { grammar csv() for str { rule field() -> String = s:$(![',']* ) { s.to_string() } pub rule record() -> Vec = fields:(field() ** ",") { fields } pub rule file() -> Vec> = lines:(record() ** "\n") "\n"? { lines } } } #[test] fn test_csv() { let input = "name,age\nalice,30\nbob,25\n"; let result = csv::file(input).unwrap(); assert_eq!(result[0], vec!["name", "age"]); assert_eq!(result[1][0], "alice"); } ``` -------------------------------- ### Parse Trait Example Implementation Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/traits.md An example implementation of the `Parse` trait for a custom type `MyType`. ```rust impl Parse for MyType { type PositionRepr = usize; fn start(&self) -> usize { 0 } fn is_eof(&self, p: usize) -> bool { p >= self.len() } fn position_repr(&self, p: usize) -> usize { p } } ``` -------------------------------- ### Lifetime Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Example of a rule with lifetime parameters. ```rust rule borrow<'a>() -> &'a str = $(...) ``` -------------------------------- ### Rule with PEG Expression Fragment Parameter Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example of a rule 'list' that accepts a PEG expression fragment parameter 'x' of type 'rule'. ```rust rule list(x: rule) -> Vec = "[" v:(x() ** ",") "]" { v } ``` -------------------------------- ### ParseSlice Trait Example Implementation Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/traits.md An example implementation of the `ParseSlice` trait for a custom type `MyTokens`. ```rust impl<'input> ParseSlice<'input> for MyTokens { type Slice = &'input [Token]; fn parse_slice(&'input self, p1: usize, p2: usize) -> &'input [Token] { &self.tokens[p1..p2] } } ``` -------------------------------- ### Parameterized Rules Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md Demonstrates the use of parameterized rules to create generic parsing logic. ```rust peg::parser! { grammar lists() for str { rule number() -> i64 = n:$(['0'..='9']+) { n.parse().unwrap() } rule list(x: rule) -> Vec = "[" v:(x() ** ",") "]" { v } pub rule numbers() -> Vec = list() } } assert_eq!(lists::numbers("[1,2,3]"), Ok(vec![1, 2, 3])); ``` -------------------------------- ### JSON Parser Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Parse JSON data structure. ```rust use std::collections::BTreeMap; #[derive(Debug, PartialEq)] pub enum Value { Null, Bool(bool), Number(f64), String(String), Array(Vec), Object(BTreeMap), } peg::parser! { grammar json() for str { rule _() = [\' \' | \'\n\' | \'\r\' | \'\t\']* rule null() -> Value = "null" { Value::Null } rule boolean() -> Value = "true" { Value::Bool(true) } / "false" { Value::Bool(false) } rule string() -> String = "\"" s:$([^\'"\']*) "\"" { s.to_string() } rule number() -> Value = n:$(['-']? ['0'..=\'9\']+ ['.']? ['0'..=\'9\']*) { Value::Number(n.parse().unwrap()) } rule array() -> Value = "[" _ v:(value() ** ("," _)) _ "]" { Value::Array(v) } rule object() -> Value = "{" _ pairs:(pair() ** ("," _)) _ "}" { Value::Object(pairs.into_iter().collect()) } rule pair() -> (String, Value) = k:string() _ ":" _ v:value() { (k, v) } rule value() -> Value = null() / boolean() / number() / string() { |s| Value::String(s) } / array() / object() pub rule parse() -> Value = _ v:value() _ { v } } } ``` -------------------------------- ### Cargo.toml Configuration Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example of how to enable the 'trace' feature for rust-peg in a Cargo.toml file. ```toml [dependencies] peg = { version = "0.8", features = ["trace"] } ``` -------------------------------- ### Type Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Example of a rule with type parameters, constrained by a trait. ```rust rule parse_as() -> T = s:$([...]+) {? s.parse().ok_or("invalid") } ``` -------------------------------- ### ParseElem Trait Example Implementation Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/traits.md An example implementation of the `ParseElem` trait for a custom type `MyTokens`. ```rust impl<'input> ParseElem<'input> for MyTokens { type Element = Token; fn parse_elem(&'input self, pos: usize) -> RuleResult { match self.tokens.get(pos) { Some(&token) => RuleResult::Matched(pos + 1, token), None => RuleResult::Failed, } } } ``` -------------------------------- ### ParseLiteral Trait Example Implementation Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/traits.md An example implementation of the `ParseLiteral` trait for a custom type `MyKeywordMap`. ```rust impl ParseLiteral for MyKeywordMap { fn parse_string_literal(&self, pos: usize, literal: &str) -> RuleResult<()> { if self.is_keyword_at(pos, literal) { RuleResult::Matched(pos + literal.len(), ()) } else { RuleResult::Failed } } } ``` -------------------------------- ### Rule with Type Parameter Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example of a rule 'seq' that accepts a type parameter 'T' with a trait bound. ```rust rule seq() -> T = s:$(['0'..='9']+) {? s.parse().ok().ok_or("number") } ``` -------------------------------- ### Precedence Climbing Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md An example of the `precedence!` macro used in an `arithmetic` rule to parse arithmetic expressions with varying operator precedence and associativity. ```rust pub rule arithmetic() -> i64 = precedence!{ x:(@) "+" y:@ { x + y } x:(@) "-" y:@ { x - y } -- x:(@) "*" y:@ { x * y } x:(@) "/" y:@ { x / y } -- x:@ "^" y:(@) { x.pow(y as u32) } // Right-associative "-" v:@ { -v } // Prefix v:@ "!" { factorial(v) } // Postfix -- n:$(['0'..='9']+) { n.parse().unwrap() } } ``` -------------------------------- ### Build Lists Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example of parsing a comma-separated list of numbers and collecting them into a Vec. ```rust rule csv() -> Vec = items:(number() ** ",") { items } ``` -------------------------------- ### No-std Support Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Illustrates how to use rust-peg with `#![no_std]` by leveraging the `alloc` crate. ```rust #![no_std] extern crate alloc; peg::parser! { grammar parser() for &'static [u8] { use alloc::vec::Vec; pub rule nums() -> Vec = ... } } ``` -------------------------------- ### Injection Variable Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example showing the 'inject' keyword to define a 'span' variable that captures the matched text range. ```rust inject span(input, lpos, rpos) -> std::ops::Range { lpos..rpos } rule foo() -> String = s:$(['a'..='z']+) { format!("{:?}", span) } ``` -------------------------------- ### Rule with Value Parameter Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md An example of a rule 'num_radix' that accepts a value parameter 'radix' of type u32. ```rust rule num_radix(radix: u32) -> u32 = n:$(['0'..='9']+) {? u32::from_str_radix(n, radix).ok().ok_or("number") } ``` -------------------------------- ### No-std Support Configuration Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/traits.md Example of how to enable no-std support for the peg crate in Cargo.toml. ```toml [dependencies] peg = { version = "0.8", default-features = false } ``` -------------------------------- ### Input with Source Locations Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Shows how to track source spans for error reporting by injecting span information into parsed nodes. ```rust use std::ops::Range; #[derive(Debug, PartialEq)] pub struct Node { pub span: Range, pub value: i64, } peg::parser! { grammar located() for str { inject span(_, start, end) -> Range { start..end } rule number() -> Node = n:$(['0'..='9']+) { Node { span, value: n.parse().unwrap(), } } pub rule parse() -> Node = number() } } #[test] fn test() { let result = located::parse("42").unwrap(); assert_eq!(result.span, 0..2); assert_eq!(result.value, 42); } ``` -------------------------------- ### Calculator Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md A PEG grammar for a simple calculator demonstrating basic rule definition, parsing of numbers, factors, terms, and expressions, including handling of whitespace and basic arithmetic operations. ```rust peg::parser! { grammar calc() for str { rule _() = [' ']* rule number() -> i64 = n:$(['0'..='9']+) _ { n.parse().unwrap() } rule factor() -> i64 = "(" _ e:expr() _ ")" { e } / number() rule term() -> i64 = a:factor() ("*" _ b:factor() { a * b })* pub rule expr() -> i64 = a:term() ("+" _ b:term() { a + b })* } } fn main() { assert_eq!(calc::expr("2 + 3 * 4"), Ok(14)); } ``` -------------------------------- ### Visibility Modifiers Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Examples of different visibility modifiers for rules. ```rust pub rule exported() = ... pub(crate) rule crate_visible() = ... rule private() = ... ``` -------------------------------- ### Example Parser Source: https://github.com/kevinmehall/rust-peg/blob/master/README.md Parse a comma-separated list of numbers surrounded by brackets into a Vec. ```rust peg::parser!{ grammar list_parser() for str { rule number() -> u32 = n:$(['0'..='9']+) {? n.parse().or(Err("u32")) } pub rule list() -> Vec = "[" l:(number() ** ",") "]" { l } } } pub fn main() { assert_eq!(list_parser::list("[1,1,2,3,5,8]"), Ok(vec![1, 1, 2, 3, 5, 8])); } ``` -------------------------------- ### PEG Expression Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Example of a rule that takes another rule as a parameter. ```rust rule list(item: rule) -> Vec = item() ** "," pub rule nums() = list() ``` -------------------------------- ### Sequence Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches expressions in order. If all match, succeed and return unit. ```rust rule foo() = "hello" " " "world" // matches input starting with "hello world" ``` -------------------------------- ### Trace Output Format Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/parser-macro.md Example output format when the `trace` feature is enabled, showing matched, attempting, and failed rule matches. ```text [PEG_TRACE] Matched rule foo at position X:Y [PEG_TRACE] Attempting to match rule bar at position X:Y [PEG_TRACE] Failed to match rule bar at position X:Y ``` -------------------------------- ### Custom Input Types Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Demonstrates using a custom token stream as input for the parser, enabling parsing of tokenized data instead of raw strings. ```rust use peg::{Parse, ParseElem, ParseLiteral, ParseSlice, RuleResult}; #[derive(Clone, Copy, Debug)] pub enum Token { Number(i32), Plus, Times, LParen, RParen, } pub struct Tokens { tokens: Vec, } impl Parse for Tokens { type PositionRepr = usize; fn start(&self) -> usize { 0 } fn is_eof(&self, p: usize) -> bool { p >= self.tokens.len() } fn position_repr(&self, p: usize) -> usize { p } } impl<'input> ParseElem<'input> for Tokens { type Element = Token; fn parse_elem(&'input self, pos: usize) -> RuleResult { match self.tokens.get(pos) { Some(&token) => RuleResult::Matched(pos + 1, token), None => RuleResult::Failed, } } } impl<'input> ParseSlice<'input> for Tokens { type Slice = &'input [Token]; fn parse_slice(&'input self, p1: usize, p2: usize) -> &'input [Token] { &self.tokens[p1..p2] } } impl ParseLiteral for Tokens { fn parse_string_literal(&self, _pos: usize, _literal: &str) -> RuleResult<()> { RuleResult::Failed } } peg::parser! { grammar calc() for Tokens { rule num() -> i32 = [Token::Number(n)] { n } rule factor() -> i32 = num() / [Token::LParen] v:expr() [Token::RParen] { v } rule term() -> i32 = l:factor() (r:([Token::Times] factor()) { l * r })* rule expr() -> i32 = l:term() (r:([Token::Plus] term()) { l + r })* pub rule parse() -> i32 = expr() } } #[test] fn test() { let tokens = Tokens { tokens: vec![Token::Number(2), Token::Plus, Token::Number(3)], }; assert_eq!(calc::parse(&tokens), Ok(5)); } ``` -------------------------------- ### Doc Comments Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Example showing how Rustdoc comments are propagated to generated modules and functions. ```rust peg::parser! { /// A simple number parser grammar parser() for str { /// Parse a single digit rule digit() -> u32 = d:['0'..='9'] { (d as u32) - 48 } /// Parse a sequence of digits pub rule number() -> u32 = n:$(['0'..='9']+) { n.parse().unwrap() } } } ``` -------------------------------- ### Handle Errors Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example of how to handle parsing errors, printing the location and expected tokens. ```rust match parser::rule(input) { Ok(value) => println!("Parsed: {:?}", value), Err(e) => eprintln!("Error at {}:{}: {}", e.location.line, e.location.column, e.expected), } ``` -------------------------------- ### Literal String Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches an exact string literal. ```rust rule foo() = "hello" // matches input starting with "hello" ``` -------------------------------- ### Lifetime Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Example of using lifetime parameters in a PEG rule. ```rust rule borrow<'a>() -> &'a str = $(['a'..='z']+) ``` -------------------------------- ### Action Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches a sequence, binds results to named variables, and executes Rust code, returning the code's value. ```rust rule number() -> i32 = n:$(['0'..='9']+) { n.parse().unwrap() } rule sum() -> i32 = a:number() "+" b:number() { a + b } rule three_chars() -> String = a:['a'] b:['b'] c:['c'] { format!("{}{}{}", a, b, c) } ``` -------------------------------- ### Pattern Matching Examples Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches single input elements against Rust match patterns. ```rust rule digit() -> char = c:['0'..='9'] { c } rule letter() = ['a'..='z' | 'A'..='Z'] rule any() = [_] ``` -------------------------------- ### Configuration File Parser Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md A PEG grammar for parsing simple configuration files with key-value settings. ```rust peg::parser! { grammar config() for str { rule _ = quiet!{[' ' | '\t' | '\n']*} rule string() -> String = "\"" s:$([^'"']*) "\"" { s.to_string() } rule identifier() -> String = s:$(['a'..='z']+) { s.to_string() } rule value() -> String = string() / identifier() rule setting() -> (String, String) = key:identifier() _ "=" _ val:value() _ ";" { (key, val) } pub rule parse() -> Vec<(String, String)> = _ settings:setting()* _ { settings } } } ``` -------------------------------- ### Visibility Modifiers Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Example demonstrating different visibility modifiers for PEG rules. ```rust peg::parser! { grammar parser() for str { rule internal() = "private" // Not exported pub rule exported() = internal() // Exported pub(crate) rule crate_visible() = "ok" // Crate-visible } } parser::exported(...)?; // OK parser::internal(...)?; // ERROR: not accessible ``` -------------------------------- ### Use Statements Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Example of importing items into grammar scope using Rust's `use` syntax. ```rust peg::parser! { grammar parser() for str { use std::str::FromStr; use my_module::{Token, parse_token}; rule number() -> i32 = ... FromStr::from_str(...) ... } } ``` -------------------------------- ### Grammar Parameters: Lifetime Parameters Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Shows an example of using lifetime parameters in grammar declarations. ```rust peg::parser!(grammar parser<'a>() for &'a str { pub rule test() -> &'a str = $(['a'..='z']+) }); ``` -------------------------------- ### Whitespace Handling Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Demonstrates how to explicitly handle whitespace in PEG grammars using a whitespace rule `_` and a rule `__` that requires whitespace. ```rust rule _ = [' ' | '\t' | '\n']* // Whitespace rule rule __ = _ &[' ' | '\t' | '\n'] // Must-have whitespace rule token(text: &'static str) = text _ // Match token and trailing space rule expr() -> i32 = a:number() _ "+" _ b:number() { a + b } ``` -------------------------------- ### Custom Error Messages Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Shows how to provide helpful parse error messages by defining custom expected error strings for rules. ```rust peg::parser! { grammar config() for str { rule _() = quiet!{[' ' | '\t']}* rule keyword(s: &'static str) = quiet!{s:$(['a'..='z']+) {? if s == s { Ok(()) } else { Err(s) } }} / expected!(s) rule identifier() -> String = s:$(['a'..='z' | '_']['a'..='z' | '0'..='9' | '_']*) { s.to_string() } / expected!("identifier") rule string() -> String = "\"" s:$([^'"']*) "\"" { s.to_string() } / expected!("string literal") rule value() -> String = string() / identifier() rule assignment() -> (String, String) = key:identifier() _ "=" _ val:value() { (key, val) } pub rule parse() -> (String, String) = _ a:assignment() _ ![_] { a } } } ``` -------------------------------- ### Parameterize Rules Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example of creating a generic rule that accepts another rule as a parameter, used here for a parameterized list. ```rust rule sep_list(item: rule) -> Vec = item() ** "," pub rule numbers() = sep_list() ``` -------------------------------- ### Parse Operators Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example using the precedence! macro to define operator precedence for arithmetic expressions. ```rust rule expr() = precedence!{ x:(@) "+" y:@ { x + y } x:(@) "*" y:@ { x * y } -- n:number() { n } } ``` -------------------------------- ### Compiler Features - Tracing Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md Example of enabling and observing parsing traces using the `trace` feature. ```rust [PEG_TRACE] Attempting to match rule expr at 2:5 [PEG_TRACE] Matched rule term at 2:7 [PEG_TRACE] Failed to match rule op at 2:8 ``` -------------------------------- ### Ordered Choice Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Tries alternatives in order and returns the result of the first matching alternative. ```rust rule keyword() -> &'static str = "if" { "if" } / "else" { "else" } / "while" { "while" } rule number_or_string() = number() / string() ``` -------------------------------- ### Splitting Grammars by Feature Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Demonstrates how to define helper functions outside the grammar for large parsers and defines a grammar for arithmetic expressions. ```rust fn combine_ops(first: i32, rest: Vec<(char, i32)>) -> i32 { rest.into_iter().fold(first, |acc, (op, val)| { match op { '+' => acc + val, '-' => acc - val, _ => unreachable!(), } }) } peg::parser! { grammar expr() for str { rule number() -> i32 = n:$(['0'..='9']+) { n.parse().unwrap() } rule op() -> char = c:['+' | '-'] { c } pub rule expr() -> i32 = first:number() rest:(op() number())* { combine_ops(first, rest) } } } ``` -------------------------------- ### Common Patterns - Whitespace Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Provides examples of PEG rules for matching zero or more whitespace characters (`_`) and one or more whitespace characters (`__`), as well as a helper for delimited rules with surrounding whitespace. ```rust rule _ = [' ' | '\t' | '\n']* rule __ = [' ' | '\t' | '\n']+ rule ws_delim(e: rule) -> T = _ v:e() _ { v } ``` -------------------------------- ### Return Value from Rule Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/README.md Example demonstrating how a rule can return a value, in this case, the sum of two parsed numbers. ```rust rule sum() -> i32 = a:number() "+" b:number() { a + b } ``` -------------------------------- ### Multiple Injections Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/advanced-features.md An example showing how to declare and use multiple injection variables within a single grammar. ```rust peg::parser! { grammar parser() for str { inject span(_, lpos, rpos) -> std::ops::Range { lpos..rpos } inject text(input, lpos, rpos) -> &'input str { &input[lpos..rpos] } pub rule word() -> (&'input str, std::ops::Range) = $(['a'..='z']+) { (text, span) } } } ``` -------------------------------- ### Left-Recursive Grammar Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/examples.md Illustrates parsing expressions with left recursion, enabling the correct evaluation of arithmetic expressions with operators like '+' and '*'. ```rust peg::parser! { grammar expr() for str { rule _() = [' ']* rule number() -> i64 = n:$(['0'..='9']+) { n.parse().unwrap() } #[cache_left_rec] rule add() -> i64 = l:add() _ "+" _ r:mul() { l + r } / mul() rule mul() -> i64 = l:mul() _ "*" _ r:number() { l * r } / number() pub rule parse() -> i64 = _ v:add() _ { v } } } #[test] fn test() { assert_eq!(expr::parse("1+2+3"), Ok(6)); // (1+2)+3 } ``` -------------------------------- ### File Structure Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/INDEX.md The directory structure of the rust-peg documentation. ```text output/ ├── INDEX.md ← You are here ├── README.md ← Start here ├── quick-reference.md ← Quick lookup ├── api-reference.md ← Architecture ├── parser-macro.md ← Main macro reference ├── expressions.md ← Expression types ├── runtime-types.md ← Error handling ├── traits.md ← Custom input types ├── advanced-features.md ← Caching, injection, etc. ├── patterns-and-best-practices.md ← Idioms & optimization └── examples.md ← Complete working examples ``` -------------------------------- ### Common Patterns - Lists Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Provides examples of PEG rules for parsing lists, including comma-separated values (CSV) and lists delimited by a specific separator, with support for different repetition counts. ```rust rule list(x: rule) -> Vec = "[" v:(x() ** ",") "]" { v } rule csv(x: rule) -> Vec = v:(x() ** ",") { v } rule sep_by_plus(x: rule, sep: rule<()>) -> Vec = v:(x() ++ (sep())) { v } ``` -------------------------------- ### RuleResult example in Custom Closure Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Demonstrates the usage of RuleResult within a custom closure in a PEG grammar. ```rust peg::parser! { grammar test() for str { rule pos() -> usize = #{ |input, pos| peg::RuleResult::Matched(pos, pos) } pub rule expr() = pos() ['a'] pos() } } ``` -------------------------------- ### Backtracking Confusion Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Explains PEG's greedy nature and demonstrates how to achieve flexible matching using lookahead or reordering rules. ```rust // PEG is greedy: once "abc" matches, tries "def" rule match_abc_or_ab() = "abc" / "ab" // Always matches abc if possible // If you want flexible matching, use lookahead or reorder rule match_ab_or_abc() = "ab" !"c" / "abc" ``` -------------------------------- ### Custom Error Messages with `quiet!` and `expected!` Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/runtime-types.md Example demonstrating custom error messages using `quiet!` and `expected!` in a rust-peg grammar. ```rust peg::parser! { grammar parser() for str { rule whitespace() = quiet!{[' ' | '\n']+} rule keyword(name: &'static str) = s:$(['a'..='z']+) {? if s == name { Ok(()) } else { Err(name) } } / expected!(name) pub rule expr() = keyword("if") } } ``` -------------------------------- ### Custom Expected with expected! Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Demonstrates using `expected!` to provide custom, user-friendly error messages when a rule fails to match, guiding the user on what was anticipated. ```rust rule keyword(name: &'static str) = s:$(['a'..='z']+) {? if s == name { Ok(()) } else { Err(name) } } / expected!(name) rule type_() = keyword("i32") / keyword("i64") / keyword("String") / expected!("type annotation") ``` -------------------------------- ### Ordered Choice for Backtracking Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Demonstrates using ordered choice `/` to try more specific rules before general ones, enabling backtracking. ```rust rule expr() -> Value // More specific pattern first = "123abc" { Value::SpecialCase } // General patterns last / number() / identifier() ``` -------------------------------- ### Grouping Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Parentheses override normal precedence. ```rust rule a() = x:number() "+" b:(number() "*" number()) { x + b } ``` -------------------------------- ### Slice Capture Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Demonstrates how to capture the matched text directly as a string slice (`&str`) or use it for transformations. ```rust // Capture matched text rule word() -> &str = $([ 'a'..='z' ]+) // Capture with transformation rule number() -> i32 = n:$([ '0'..='9' ]+) { n.parse().unwrap() } // Capture vs result rule hex() -> String = "0x" hex:$(['0'..='9' | 'a'..='f']+) { hex.to_string() } ``` -------------------------------- ### Zero or More Repetition Examples Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches zero or more repetitions of an expression. ```rust rule numbers() -> Vec = nums:number()* { nums } rule csv() -> Vec = items:(string() ** ",") { items } ``` -------------------------------- ### Expression Syntax Cheatsheet - Combining Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/quick-reference.md Shows how to combine PEG expressions using sequences, actions with bindings, conditional actions, and ordered choices. ```rust e1 e2 e3 // Sequence (all must match) a:e1 b:e2 { code } // Action with bindings a:e1 {? result_expr } // Conditional action e1 / e2 / e3 // Ordered choice ``` -------------------------------- ### Optional Repetition Example Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches zero or one repetition of an expression. ```rust rule int() -> i32 = sign:['-']? n:$(['0'..='9']+) { let n: i32 = n.parse().unwrap(); match sign { Some('-') => -n, _ => n, } } ``` -------------------------------- ### Rule Call Examples Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Calls another rule defined in the grammar. ```rust rule number() -> i32 = n:$(['0'..='9']+) { n.parse().unwrap() } rule expr() = number() "+" number() // With arguments rule seq(n: usize) = ['a']*<{n}> pub rule parse() = seq(5) ``` -------------------------------- ### Inverted Pattern Examples Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/expressions.md Matches single elements that do NOT match the pattern. ```rust rule non_space() = [^ ' '] rule not_eof() = [^_] // Match anything except EOF ``` -------------------------------- ### Reusable Grammar Patterns Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Shows how to define reusable patterns as helper rules for common structures like lists and pairs, and a grammar for parsing configuration. ```rust peg::parser! { grammar parsers() for str { rule _() = [' ']* rule _ = _() rule number() -> i32 = n:$(['0'..='9']+) _ { n.parse().unwrap() } rule string() -> String = """ s:$([^'"']*) """ _ { s.to_string() } // Reusable list pattern rule list(item: rule) -> Vec = "[" _ items:(item() ** ("," _)) _ "]" { items } // Reusable pair pattern rule pair(a: rule, b: rule) -> (A, B) = "(" _ x:a() _ "," _ y:b() _ ")" { (x, y) } pub rule config() = list(, )>) } } ``` -------------------------------- ### Infinite Loops in Repetition Source: https://github.com/kevinmehall/rust-peg/blob/master/_autodocs/patterns-and-best-practices.md Illustrates how incorrect use of repetition operators can lead to infinite loops and provides corrected versions. ```rust // Wrong: * allows zero repetitions, can loop forever rule expr() = expr()* // Right: require at least one element rule expr() = expr()+ // Even better: use choice to base case rule expr() = "base" / expr() "+" expr() ```