Minimal Imperative Parsing Library | https://docs.rs/mipl
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}