Parser

Trait Parser 

Source
pub trait Parser<Ctx>: Default {
    type Value;

    // Required method
    fn parse<'a>(
        &self,
        input: TokenStream<'a>,
        ctx: Ctx,
    ) -> ParseResult<'a, Self::Value>;
}
Expand description

Definition of the parsing and completion algorithm for some type

This trait is fundamental for the functionality of kmdparse. The implementers must define two operations: parsing (converting the input TokenStream into a value of a target type) and completion (generating the set of possible completions for the last meaningful token in the input stream).

Most often, the types being parsed are compound, meaning they contain multiple fields with different parsers. It is best to keep parsers as simple as possible and delegate most of the work to the child parsers. To ensure correct interaction between parsers, custom implementations must follow the parsing protocol. The rules are described in the documentation for each of the Parser’s methods.

Please note, that in most cases writing the parser by hand isn’t necessary. Parser is automatically generated for any type that derives Parsable. The name of the generated parser is constructed by appending the word Parser to the end of the type.

§Context

The Parser trait is generic over an arbitrary context. Context is passed as an argument to both of the Parser’s methods and is intended to make parsers configurable, meaning their behavior can depend on some information available at runtime.

The following example demonstrates how to implement the parser for a variant-like data, dependent on data available at runtime.

use kmdparse::{Parser, CompletionResult, ParseResult, parse_parser, complete_parser};
use kmdparse::tokens::{TokenStream, Token};
use kmdparse::error::{ParseError, UnrecognizedToken};
use std::borrow::Cow;
use std::collections::{BTreeSet, HashMap};

struct RuntimeContext { variables: HashMap<String, u32> }

#[derive(Default)]
struct VariableParser;

impl<'c> Parser<&'c RuntimeContext> for VariableParser {
    type Value = u32;

    fn parse<'a>(&self, input: TokenStream<'a>, ctx: &'c RuntimeContext) -> ParseResult<'a, Self::Value> {
        match input.take().transpose()? {
            None => Err(ParseError::token_required().expected("variable").into()),
            Some((attr @ Token::Attribute(_), remaining)) => {
                Err(UnrecognizedToken::new(attr, remaining).into())
            }
            Some((token @ Token::Text(text), remaining)) => {
                let text = text.parse_string();
                match ctx.variables.get(&text as &str) {
                    Some(value) => Ok((*value, remaining)),
                    None => Err(UnrecognizedToken::new(token, remaining).into()),
                }
            }
        }
    }

    fn complete<'a>(&self, input: TokenStream<'a>, ctx: &'c RuntimeContext) -> CompletionResult<'a> {
        match input.take() {
            Some(Err(_)) | None => CompletionResult::new_final(false),
            Some(Ok((Token::Attribute(_), _))) => CompletionResult::new(input, false),
            Some(Ok((Token::Text(text), remaining))) if remaining.is_all_consumed() => {
                let text = text.parse_string();
                CompletionResult::new_final(true).add_suggestions(
                    ctx.variables.keys()
                        .filter_map(|key| key.strip_prefix(&text as &str))
                        .map(|suggestion| Cow::Owned(suggestion.to_string()))
                )
            }
            Some(Ok((Token::Text(_), remaining))) => CompletionResult::new(remaining, true),
        }
    }
}

let context = RuntimeContext {
    variables: HashMap::from([("var-1".to_string(), 10), ("var-2".to_string(), 20)]),
};

assert_eq!(parse_parser::<_, VariableParser>("var-1", &context)?, 10);
assert_eq!(parse_parser::<_, VariableParser>("var-2", &context)?, 20);
assert_eq!(
    complete_parser::<_, VariableParser>("va", &context),
    BTreeSet::from(["r-1".into(), "r-2".into()]),
);

Parser implementation should be as generic as possible to avoid type errors when integrating with other parsers.

Required Associated Types§

Source

type Value

The type that this parser will parse the input stream into.

Required Methods§

Source

fn parse<'a>( &self, input: TokenStream<'a>, ctx: Ctx, ) -> ParseResult<'a, Self::Value>

Parsers the beginning of the token stream into a Value.

This function performs the parsing of the input stream: it repeatedly consumes tokens from the token stream and then produces one of the following return values:

  • Ok((value, remaining)) in case of the correctly parsed sequence of tokens. Here value is the result of the parsing, (it has type Self::Value), and remaining is the token stream representing the set of tokens that wasn’t consumed;
  • Err(ParseFailure::Error(error)) in case the parser failed with an error indicating the malformed input. See ParseError;
  • Err(ParseFailure::Unexpected(unexpected_token)) if the first token in the input stream is an attribute or an enum variant discriminator that the parser does not recognize.

To be interoperable with other parsers, the parse implementation must follow the parsing protocol:

  • if the first token in the input stream is an attribute and the parser does not recognize this attribute, it should return Err(UnexpectedToken::new(token, remaining).into()) where token is the attribute that was not recognized, and remaining is the token stream consisting of tokens directly following token;
  • if the parser expects the enum variant discriminator and the first token of the input is not recognized as such, it should return Err(UnexpectedToken::new(token, remaining).into()) with the same values as described above;
  • the parser must not return [UnexpectedToken] result with any token other than the first token of the input stream; if it receives this value from an inner parser, it must convert it into the equivalent error if the parser was not called on the original input;
  • when all required tokens are successfully consumed parser should continue to take tokens until a text token or an attribute that is not recognized is encountered (this is not necessary if parser does not expect attributes)

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<Ctx> Parser<Ctx> for BooleanParser

Source§

impl<Ctx> Parser<Ctx> for PathParser

Available on crate feature std only.
Source§

impl<Ctx> Parser<Ctx> for StringParser

Available on crate feature std only.
Source§

impl<Ctx, P, T, O> Parser<Ctx> for TransformParser<P, T, O>
where P: Parser<Ctx>, T: ParsableTransformation<O, Input = P::Value>,

Source§

type Value = O

Source§

impl<Ctx, P: Parser<Ctx>> Parser<Ctx> for OptionParser<P>

Source§

type Value = Option<<P as Parser<Ctx>>::Value>

Source§

impl<Ctx, T: Default> Parser<Ctx> for DefaultValueParser<T>

Source§

type Value = T

Source§

impl<Ctx, const N: usize> Parser<Ctx> for HeaplessStringParser<N>

Source§

type Value = StringInner<usize, VecStorageInner<[MaybeUninit<u8>; N]>>

Source§

impl<Ctx: Clone, C: ParsableCollection + Default, P: Parser<Ctx, Value = C::Item>> Parser<Ctx> for CollectionParser<C, P>

Source§

type Value = C

Source§

impl<Ctx: Clone, T1: Parser<Ctx>> Parser<Ctx> for TupleParser1<T1>

Source§

type Value = (<T1 as Parser<Ctx>>::Value,)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>> Parser<Ctx> for TupleParser2<T1, T2>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>> Parser<Ctx> for TupleParser3<T1, T2, T3>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>> Parser<Ctx> for TupleParser4<T1, T2, T3, T4>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>> Parser<Ctx> for TupleParser5<T1, T2, T3, T4, T5>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>> Parser<Ctx> for TupleParser6<T1, T2, T3, T4, T5, T6>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>> Parser<Ctx> for TupleParser7<T1, T2, T3, T4, T5, T6, T7>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>> Parser<Ctx> for TupleParser8<T1, T2, T3, T4, T5, T6, T7, T8>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>> Parser<Ctx> for TupleParser9<T1, T2, T3, T4, T5, T6, T7, T8, T9>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>> Parser<Ctx> for TupleParser10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>> Parser<Ctx> for TupleParser11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>, T12: Parser<Ctx>> Parser<Ctx> for TupleParser12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value, <T12 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>, T12: Parser<Ctx>, T13: Parser<Ctx>> Parser<Ctx> for TupleParser13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value, <T12 as Parser<Ctx>>::Value, <T13 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>, T12: Parser<Ctx>, T13: Parser<Ctx>, T14: Parser<Ctx>> Parser<Ctx> for TupleParser14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value, <T12 as Parser<Ctx>>::Value, <T13 as Parser<Ctx>>::Value, <T14 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>, T12: Parser<Ctx>, T13: Parser<Ctx>, T14: Parser<Ctx>, T15: Parser<Ctx>> Parser<Ctx> for TupleParser15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value, <T12 as Parser<Ctx>>::Value, <T13 as Parser<Ctx>>::Value, <T14 as Parser<Ctx>>::Value, <T15 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T1: Parser<Ctx>, T2: Parser<Ctx>, T3: Parser<Ctx>, T4: Parser<Ctx>, T5: Parser<Ctx>, T6: Parser<Ctx>, T7: Parser<Ctx>, T8: Parser<Ctx>, T9: Parser<Ctx>, T10: Parser<Ctx>, T11: Parser<Ctx>, T12: Parser<Ctx>, T13: Parser<Ctx>, T14: Parser<Ctx>, T15: Parser<Ctx>, T16: Parser<Ctx>> Parser<Ctx> for TupleParser16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>

Source§

type Value = (<T1 as Parser<Ctx>>::Value, <T2 as Parser<Ctx>>::Value, <T3 as Parser<Ctx>>::Value, <T4 as Parser<Ctx>>::Value, <T5 as Parser<Ctx>>::Value, <T6 as Parser<Ctx>>::Value, <T7 as Parser<Ctx>>::Value, <T8 as Parser<Ctx>>::Value, <T9 as Parser<Ctx>>::Value, <T10 as Parser<Ctx>>::Value, <T11 as Parser<Ctx>>::Value, <T12 as Parser<Ctx>>::Value, <T13 as Parser<Ctx>>::Value, <T14 as Parser<Ctx>>::Value, <T15 as Parser<Ctx>>::Value, <T16 as Parser<Ctx>>::Value)

Source§

impl<Ctx: Clone, T: Parsable<Ctx> + Copy + Default, const N: usize, const FILL: bool> Parser<Ctx> for ParsableArray<T, N, FILL>

Source§

type Value = ParsableArray<T, N, FILL>

Source§

impl<T, Ctx> Parser<Ctx> for IntegerParser<T>
where T: FromStr<Err = ParseIntError>,

Source§

type Value = T

Source§

impl<T: FromStr, Ctx> Parser<Ctx> for FromStrParser<T>

Source§

type Value = T