Rule

Trait Rule 

Source
pub trait Rule<'input, SliceType: ?Sized + 'input>: NamedRule {
    type Output;

Show 14 methods // Required method fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input SliceType, index: &'index mut usize, ) -> Result<Self::Output, ParseError> where 'input: 'this; // Provided methods fn parse<'this>( &'this self, input: &'input SliceType, ) -> Result<(&'input SliceType, Self::Output), ParseError> where 'input: 'this { ... } fn map_parsed<Output, F: Fn(Self::Output) -> Output>( self, function: F, ) -> Map<'input, SliceType, Self, Output, F> where Self: Sized { ... } fn try_map_parsed<Output, E: Error + 'static, F: Fn(Self::Output) -> Result<Output, E>>( self, function: F, ) -> TryMap<'input, SliceType, Self, Output, E, F> where Self: Sized { ... } fn prevent(self) -> Not<Self> where Self: Sized { ... } fn repeat_for<const REPS: usize>( self, ) -> RepeatFor<'input, SliceType, Self, REPS> where Self: Sized { ... } fn repeat(self, reps: usize) -> Repeat<'input, SliceType, Self> where Self: Sized { ... } fn take(self, at_most: usize) -> Many<'input, SliceType, Self> where Self: Sized { ... } fn hoard(self) -> Many<'input, SliceType, Self> where Self: Sized { ... } fn take_sep<R: Rule<'input, SliceType>>( self, separator: R, at_most: usize, ) -> Separated<'input, SliceType, Self, R> where Self: Sized { ... } fn hoard_sep<R: Rule<'input, SliceType>>( self, separator: R, ) -> Separated<'input, SliceType, Self, R> where Self: Sized { ... } fn consume_all(self) -> Consume<'input, SliceType, Self> where Self: Sized, Consume<'input, SliceType, Self>: Rule<'input, SliceType, Output = Vec<Self::Output>> { ... } fn spanned(self) -> Spanned<'input, SliceType, Self> where Self: Sized, SliceType: Index<RangeTo<usize>, Output = SliceType> { ... } fn attempt(self) -> Attempt<'input, SliceType, Self> where Self: Sized { ... }
}
Expand description

Trait dictating that something can be used as a rule within a parsing grammar.

§Implementation

Imlpementing this trait means that anyone can use your struct as a rule in any of their their grammars with a supported slice type.

If you’re defining simple rules that don’t depend on the input, you can make rules generic over all slice types!

This is done for most of the “helper rules”, like Any, in this crate.

Required Associated Types§

Source

type Output

The type of the value of a successful parse of this rule.

Required Methods§

Source

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input SliceType, index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Parses a rule at a given index with a given input.

§Errors

Errors if the rule fails to parse.

§Correctness

When a parse succeeds, you must replace the borrowed input and index with a slice of it past the index you stopped parsing at - for example,

*input = &input[2..];
*index += 2;

You also must reset the values of input and index if an error occurs.

For example, this can be done as follows:

let before = (*input, *index);
// later...
let res = match inner_rule.parse_at(input, index) {
    Ok(v) => v,
    Err(err) => {
        (*input, *index) = before;
        return Err(err);
    }
}

Fsilure to do uphold of these could cause other code using your rule to misbehave, potentially inducing panics and/or non-termination.

As this is not a safety contract, implementors cannot rely on this for soundness in unsafe code.

Provided Methods§

Source

fn parse<'this>( &'this self, input: &'input SliceType, ) -> Result<(&'input SliceType, Self::Output), ParseError>
where 'input: 'this,

Parses a given rule at the start of some input.

§Errors

Errors if the rule fails to parse.

Examples found in repository?
examples/math.rs (line 104)
89fn main() -> Result<(), std::io::Error> {
90    let mut lines = std::io::stdin().lines();
91    println!("Input a math expression below, `clear` to clear the console, or `exit` / `quit` to exit.");
92    println!("You can access the result of the last expression with `ans`.");
93    let mut last_ans = None;
94    'outer: loop {
95        print!("[?] ");
96        std::io::stdout().flush()?;
97        let Some(input) = lines.next().transpose()? else { break Ok(()) };
98        let input = input.trim_ascii();
99        if input.is_empty() { print!("\x1b[1A"); continue; }
100        match input {
101            "clear" => print!("\x1bc"),
102            "exit" | "quit" => break Ok(()),
103            _ => {
104                let (_, mut tokens) = match MathTokens::LangTokens.parse(&input) {
105                    Ok(v) => v,
106                    Err(err) => {
107                        println!("[!] Failed to parse: {err}");
108                        continue;
109                    }
110                };
111                for ans in tokens.iter_mut().filter(|t| matches!(t, Token::Ans)) {
112                    let Some(answer) = last_ans else {
113                        println!("[!] No previous answer exists");
114                        continue 'outer;
115                    };
116                    *ans = Token::Number(answer);
117                }
118                let (_, result) = match TokenMath::Expr.parse(tokens.as_ref()) {
119                    Ok(v) => v,
120                    Err(err) => {
121                        println!("[!] Failed to parse: {err}");
122                        continue;
123                    }
124                };
125                last_ans = Some(result);
126                println!("[=] {result:.}")
127            } 
128        }
129    }
130}
Source

fn map_parsed<Output, F: Fn(Self::Output) -> Output>( self, function: F, ) -> Map<'input, SliceType, Self, Output, F>
where Self: Sized,

Maps an infallible function onto the output of a rule.

Examples found in repository?
examples/math.rs (line 19)
18        pub LangTokens -> Vec<Token> = LangToken.consume_all()
19            .map_parsed(|v| v.into_iter().filter_map(|v| v).collect() );
Source

fn try_map_parsed<Output, E: Error + 'static, F: Fn(Self::Output) -> Result<Output, E>>( self, function: F, ) -> TryMap<'input, SliceType, Self, Output, E, F>
where Self: Sized,

Maps a function onto the output of a rule, passing the error back if it fails.

Source

fn prevent(self) -> Not<Self>
where Self: Sized,

Matches when this fails, and vice versa.

Source

fn repeat_for<const REPS: usize>( self, ) -> RepeatFor<'input, SliceType, Self, REPS>
where Self: Sized,

Repeats this rule a known amount of times.

Source

fn repeat(self, reps: usize) -> Repeat<'input, SliceType, Self>
where Self: Sized,

Repeats this rule a set amount of times.

Source

fn take(self, at_most: usize) -> Many<'input, SliceType, Self>
where Self: Sized,

Repeats this rule at most a set amount of times.

Source

fn hoard(self) -> Many<'input, SliceType, Self>
where Self: Sized,

Repeats this rule forever until it fails.

Source

fn take_sep<R: Rule<'input, SliceType>>( self, separator: R, at_most: usize, ) -> Separated<'input, SliceType, Self, R>
where Self: Sized,

Repeats this rule at most a set amount of times, separated by another rule.

Source

fn hoard_sep<R: Rule<'input, SliceType>>( self, separator: R, ) -> Separated<'input, SliceType, Self, R>
where Self: Sized,

Repeats this rule forever until it fails, separated by another rule.

Source

fn consume_all(self) -> Consume<'input, SliceType, Self>
where Self: Sized, Consume<'input, SliceType, Self>: Rule<'input, SliceType, Output = Vec<Self::Output>>,

Repeats this rule until the end of input, failing if it ever does.

Examples found in repository?
examples/math.rs (line 18)
18        pub LangTokens -> Vec<Token> = LangToken.consume_all()
19            .map_parsed(|v| v.into_iter().filter_map(|v| v).collect() );
20        LangToken -> Option<Token> = 
21            Num : Plus : Minus : Asterisk : Slash : Percent : Carat
22            : LParen : RParen : Ans : _ Whitespace 
23            : InvalidChar;
24        // Since Fail returns !, we can coerce from that to a token
25        InvalidChar -> Token from(|_, n| n) = Any, Fail::new(Unexpected::new(arg_0));
26
27        Plus -> Token = '+'.map_parsed(|_| Token::Plus);
28        Minus -> Token = '-'.map_parsed(|_| Token::Minus);
29        Asterisk -> Token = '*'.map_parsed(|_| Token::Asterisk);
30        Slash -> Token = '/'.map_parsed(|_| Token::Slash);
31        Percent -> Token = '%'.map_parsed(|_| Token::Percent);
32        Carat -> Token = '^'.map_parsed(|_| Token::Carat);
33        LParen -> Token = '('.map_parsed(|_| Token::LeftParen);
34        RParen -> Token = ')'.map_parsed(|_| Token::RightParen);
35
36        Ans -> Token = "ans".map_parsed(|_| Token::Ans);
37
38        Num -> Token from(|n| Token::Number(n)) = 
39            ("nan", "NaN").map_parsed(|_| f64::NAN) : 
40            ("inf", "Infinity").map_parsed(|_| f64::INFINITY) : 
41            Float;
42        Float -> f64 try_from(f64::from_str) = FloatTokens.spanned().map_parsed(|span| span.source);
43        
44        FloatTokens -> () = _ UInt, _ FloatFract.attempt(), _ FloatExp.attempt();
45        FloatFract -> () = _ '.', _ UInt;
46        FloatExp -> () = _ ('e', 'E'), _ ('-', '+').attempt(), _ UInt;
47
48        UInt -> &'input str = While::from(char::is_ascii_digit);
49    }
50}
51
52define! {
53    grammar TokenMath<[Token]> {
54        pub Expr -> f64 from(parse_expr) = Prod, SumSuf.consume_all();
Source

fn spanned(self) -> Spanned<'input, SliceType, Self>
where Self: Sized, SliceType: Index<RangeTo<usize>, Output = SliceType>,

Captures the output and span of this rule, returning them along with the output in a Span.

Source

fn attempt(self) -> Attempt<'input, SliceType, Self>
where Self: Sized,

Tries to capture this rule, returning None if it doesn’t match.

Implementations on Foreign Types§

Source§

impl<'input> Rule<'input, str> for char

Source§

type Output = char

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input str, index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input> Rule<'input, str> for fn(&char) -> bool

Source§

type Output = char

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input str, index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input> Rule<'input, str> for str

Source§

type Output = &'input str

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input str, index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input, S: ?Sized + 'input, T: ?Sized + Rule<'input, S>> Rule<'input, S> for &T

Source§

type Output = <T as Rule<'input, S>>::Output

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input S, index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input, SliceType: ?Sized + 'input, Output, T> Rule<SliceType> for (T₁, T₂, …, Tₙ)
where T: Rule<'input, SliceType, Output = Output>,

For tuples up to arity 16, Rule is implemented as a sort of “anonymous group”, where each rule will be tried in sequence until one matches, or an error will be raised if none do.

The more_tuple_impls feature raises the implemented arity to 256, but massively increases compilation time. Use only when strictly necessary.

Source§

type Output = Output

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input SliceType, index: &'index mut usize, ) -> Result<Output, ParseError>
where 'input: 'this,

Source§

impl<'input, T: 'input> Rule<'input, [T]> for for<'a> fn(&'a T) -> bool

Source§

type Output = &'input T

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input [T], index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input, T: PartialEq + 'input> Rule<'input, [T]> for [T]

Source§

type Output = &'input [T]

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input [T], index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'input, const N: usize, T: PartialEq + 'input> Rule<'input, [T]> for [T; N]

Source§

type Output = &'input [T]

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'input [T], index: &'index mut usize, ) -> Result<Self::Output, ParseError>
where 'input: 'this,

Source§

impl<'ty, T, S: ?Sized> Rule<'ty, S> for for<'index, 'cursor> fn(&'cursor mut &'ty S, &'index mut usize) -> Result<T, ParseError>

Source§

type Output = T

Source§

fn parse_at<'cursor, 'this, 'index>( &'this self, input: &'cursor mut &'ty S, index: &'index mut usize, ) -> Result<T, ParseError>
where 'ty: 'this,

Implementors§

Source§

impl<'i, S: 'i + ?Sized, O, F: FnMut() -> O> Rule<'i, S> for Action<O, F>

Source§

impl<'input> Rule<'input, str> for Any

Source§

impl<'input, F: Fn(&char) -> bool> Rule<'input, str> for While<F, char>

Source§

type Output = &'input str

Source§

impl<'input, R: Rule<'input, str>> Rule<'input, str> for Consume<'input, str, R>

Source§

type Output = Vec<<R as Rule<'input, str>>::Output>

Source§

impl<'input, SliceType: ?Sized, R: Rule<'input, SliceType>, O, E: Error + 'static, Func: Fn(R::Output) -> Result<O, E>> Rule<'input, SliceType> for TryMap<'input, SliceType, R, O, E, Func>

Source§

impl<'input, SliceType: ?Sized, R: Rule<'input, SliceType>, O, Func: Fn(R::Output) -> O> Rule<'input, SliceType> for Map<'input, SliceType, R, O, Func>

Source§

type Output = <Func as FnOnce(<R as Rule<'input, SliceType>>::Output)>::Output

Source§

impl<'input, T: 'input + Index<RangeTo<usize>, Output = T> + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Spanned<'input, T, R>

Source§

type Output = Span<'input, T, <R as Rule<'input, T>>::Output>

Source§

impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Attempt<'input, T, R>

Source§

type Output = Result<<R as Rule<'input, T>>::Output, ParseError>

Source§

impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Many<'input, T, R>

Source§

type Output = Vec<<R as Rule<'input, T>>::Output>

Source§

impl<'input, T: 'input + ?Sized, R: Rule<'input, T>> Rule<'input, T> for Repeat<'input, T, R>

Source§

type Output = Vec<<R as Rule<'input, T>>::Output>

Source§

impl<'input, T: 'input + ?Sized, R: Rule<'input, T>, S: Rule<'input, T>> Rule<'input, T> for Separated<'input, T, R, S>

Source§

type Output = Vec<(<R as Rule<'input, T>>::Output, Option<<S as Rule<'input, T>>::Output>)>

Source§

impl<'input, T: 'input + ?Sized, R: Rule<'input, T>, const REPETITIONS: usize> Rule<'input, T> for RepeatFor<'input, T, R, REPETITIONS>

Source§

type Output = [<R as Rule<'input, T>>::Output; REPETITIONS]

Source§

impl<'input, T: 'input> Rule<'input, [T]> for Any

Source§

impl<'input, T: 'input, F: Fn(&T) -> bool> Rule<'input, [T]> for While<F, T>

Source§

type Output = &'input [T]

Source§

impl<'input, T: 'input, R: Rule<'input, [T]>> Rule<'input, [T]> for Consume<'input, [T], R>

Source§

type Output = Vec<<R as Rule<'input, [T]>>::Output>

Source§

impl<'input, T: ?Sized + 'input, E: Error + Clone + 'static> Rule<'input, T> for Fail<E>

Source§

type Output = <fn() -> ! as FnOnce<()>>::Output

Source§

impl<'input, T: ?Sized + 'input, R: Rule<'input, T>> Rule<'input, T> for Not<R>