Minimal Imperative Parsing Library | https://docs.rs/mipl
at main 114 lines 3.4 kB view raw
1//! Concrete parsers. These take [Parser] and provide 2//! more specific ways to peek and advance tokens. 3 4use super::*; 5 6/// Interface for the items to peek. 7pub trait PeekerItem: Sized { 8 /// Converts a token to the type of items to peek. 9 fn from_tok(token: Token) -> Option<Self>; 10} 11impl PeekerItem for String { 12 fn from_tok(token: Token) -> Option<Self> { 13 if let Token::Str(s) = token { 14 Some(s) 15 } else { 16 None 17 } 18 } 19} 20 21/// The peeking functionality of concrete parsers. 22pub trait Peeker { 23 /// The type of the elements. 24 type Item: PeekerItem; 25 26 /// Peek for the next [Token] that satisfies some criteria defined 27 /// by the implementation of this function. 28 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token>; 29 30 /// Peek for the next element. Implemented based on 31 /// [Peeker::peek_for_token]. 32 fn peek_for(&self, parser: &mut Parser) -> Option<Self::Item> { 33 Self::Item::from_tok( 34 self.peek_for_token(parser)? 35 ) 36 } 37} 38 39/// Marks [ContainerCp] input types at the trait-level. 40pub trait IsContainerCpInput {} 41/// Marks [ContainerCp] types at the trait-level. 42pub trait ContainedType {} 43 44/// Interface for containing data in the concrete parser structs. 45pub trait ContainerCp { 46 /// The type the concrete parsers are constructed from. 47 type Input: IsContainerCpInput; 48 /// The type the concrete parser structs contain. 49 type ContainedType: ContainedType; 50 51 /// Creates a new instance of the type to be contained. 52 fn new_contained(value: Self::Input) -> Self::ContainedType; 53 /// Creates a new parser struct based on the expected input type. 54 fn new(value: Self::Input) -> Self; 55} 56 57/// Along with [Peeker], defines the core functionality 58/// of concrete parsers. 59/// 60/// Has blanket implementation for all concrete parsers. 61pub trait ConcreteParser: Peeker + ContainerCp { 62 /// Peek the next token in the [Parser] stream. If it 63 /// satisfies the criteria as specified by the [Peeker] 64 /// implementation, consume and return the [Token]. 65 fn try_next_token(&self, parser: &mut Parser) -> Option<Token>; 66 /// Try to advance to the next element. Implemented based on 67 /// [ConcreteParser::try_next_token]. 68 /// 69 /// If the inner `try_next_token` consumes and returns the token, 70 /// constructs and returns the element from it. 71 /// 72 /// Return type is the same as that of [Peeker::peek_for]. 73 fn try_next(&self, parser: &mut Parser) -> Option<Self::Item> { 74 Self::Item::from_tok( 75 self.try_next_token(parser)? 76 ) 77 } 78} 79 80impl<T> ConcreteParser for T 81where 82 T: Peeker + ContainerCp 83{ 84 fn try_next_token(&self, parser: &mut Parser) -> Option<Token> { 85 if let Some(tok) = self.peek_for_token(parser) { 86 parser.next(); 87 Some(tok) 88 } else { 89 None 90 } 91 } 92} 93 94impl IsContainerCpInput for String {} 95impl ContainedType for String {} 96 97impl IsContainerCpInput for () {} 98impl ContainedType for () {} 99 100mod exact_match; 101mod or_exact_match; 102mod any_str_match; 103mod is_newline; 104mod is_tab; 105/// All concrete parsers. 106pub mod list { 107 pub use super::{ 108 exact_match::ExactMatch, 109 or_exact_match::OrExactMatch, 110 any_str_match::AnyStrMatch, 111 is_newline::IsNewline, 112 is_tab::IsTab 113 }; 114}