//! Concrete parsers. These take [Parser] and provide //! more specific ways to peek and advance tokens. use super::*; /// Interface for the items to peek. pub trait PeekerItem: Sized { /// Converts a token to the type of items to peek. fn from_tok(token: Token) -> Option; } impl PeekerItem for String { fn from_tok(token: Token) -> Option { if let Token::Str(s) = token { Some(s) } else { None } } } /// The peeking functionality of concrete parsers. pub trait Peeker { /// The type of the elements. type Item: PeekerItem; /// Peek for the next [Token] that satisfies some criteria defined /// by the implementation of this function. fn peek_for_token(&self, parser: &mut Parser) -> Option; /// Peek for the next element. Implemented based on /// [Peeker::peek_for_token]. fn peek_for(&self, parser: &mut Parser) -> Option { Self::Item::from_tok( self.peek_for_token(parser)? ) } } /// Marks [ContainerCp] input types at the trait-level. pub trait IsContainerCpInput {} /// Marks [ContainerCp] types at the trait-level. pub trait ContainedType {} /// Interface for containing data in the concrete parser structs. pub trait ContainerCp { /// The type the concrete parsers are constructed from. type Input: IsContainerCpInput; /// The type the concrete parser structs contain. type ContainedType: ContainedType; /// Creates a new instance of the type to be contained. fn new_contained(value: Self::Input) -> Self::ContainedType; /// Creates a new parser struct based on the expected input type. fn new(value: Self::Input) -> Self; } /// Along with [Peeker], defines the core functionality /// of concrete parsers. /// /// Has blanket implementation for all concrete parsers. pub trait ConcreteParser: Peeker + ContainerCp { /// Peek the next token in the [Parser] stream. If it /// satisfies the criteria as specified by the [Peeker] /// implementation, consume and return the [Token]. fn try_next_token(&self, parser: &mut Parser) -> Option; /// Try to advance to the next element. Implemented based on /// [ConcreteParser::try_next_token]. /// /// If the inner `try_next_token` consumes and returns the token, /// constructs and returns the element from it. /// /// Return type is the same as that of [Peeker::peek_for]. fn try_next(&self, parser: &mut Parser) -> Option { Self::Item::from_tok( self.try_next_token(parser)? ) } } impl ConcreteParser for T where T: Peeker + ContainerCp { fn try_next_token(&self, parser: &mut Parser) -> Option { if let Some(tok) = self.peek_for_token(parser) { parser.next(); Some(tok) } else { None } } } impl IsContainerCpInput for String {} impl ContainedType for String {} impl IsContainerCpInput for () {} impl ContainedType for () {} mod exact_match; mod or_exact_match; mod any_str_match; mod is_newline; mod is_tab; /// All concrete parsers. pub mod list { pub use super::{ exact_match::ExactMatch, or_exact_match::OrExactMatch, any_str_match::AnyStrMatch, is_newline::IsNewline, is_tab::IsTab }; }