···1212 DelimitersParam,
1313 };
1414}
1515+/// The lexer prelude.
1616+pub mod prelude {
1717+ pub use super::*;
1818+ pub use super::del::*;
1919+}
15201621/// Type for marking expected [Token::End] cases.
1722#[derive(Debug, PartialEq, Clone)]
···4954 ));
5055 }
51565757+ /// Add a token to the list ad-hoc.
5858+ pub fn add_token(&mut self, token: Token) {
5959+ self.0.push_back(token)
6060+ }
6161+6262+ /// Get a new empty list of tokens.
6363+ pub fn new_empty() -> Tokens {
6464+ Tokens(VecDeque::new())
6565+ }
6666+5267 /// Tokenize string input.
5368 pub fn new<T: AsRef<str>>(
5469 value: T,
+16-1
src/lib.rs
···22#![warn(missing_docs)]
3344pub mod lexer;
55-pub mod parser;55+pub mod parser;
66+77+/// The prelude for `mipl`
88+pub mod prelude {
99+ pub use super::{
1010+ lexer::{
1111+ *,
1212+ del::*
1313+ },
1414+ parser::{
1515+ *,
1616+ parsers::*,
1717+ subparser::*
1818+ }
1919+ };
2020+}
+1-5
src/parser.rs
···11//! The Parser.
22-use crate::lexer::{
33- del::DelimitersParam,
44- Tokens,
55- Token
66-};
22+use crate::lexer::prelude::*;
73use std::iter::Peekable;
8495/// Contains both the token stream and the parsing functionalities.
+26-9
src/parser/parsers.rs
···5566/// The peeking functionality of concrete parsers.
77///
88-pub trait PeekerOperator<Item> {
88+pub trait PeekerOperator {
99+ /// The type of the elements.
1010+ type Item;
1111+912 /// Returns the `Item` if it matches some pattern as
1013 /// defined by the implementation of this function
1114 /// for any particular parser.
···1316 /// Returns `None` for non-matching tokens. This behavior
1417 /// is used to automatically derive [Operator] implementation
1518 /// over certain generics.
1616- fn peek_for(&self, parser: &mut Parser) -> Option<Item>;
1919+ fn peek_for(&self, parser: &mut Parser) -> Option<Self::Item>;
1720}
18212222+/// Marks container input types at the trait-level.
2323+pub trait IsContainerInput {}
2424+/// Marks container types at the trait-level.
2525+pub trait ContainedType {}
2626+2727+/// Interface for containing data in the concrete parser structs.
1928pub trait Container {
2020- type Input;
2121- type ContainedType;
2929+ /// The type the concrete parsers are constructed from.
3030+ type Input: IsContainerInput;
3131+ /// The type the concrete parser structs contain.
3232+ type ContainedType: ContainedType;
22333434+ /// Created a new instance of the type to be contained.
2335 fn new_contained(value: Self::Input) -> Self::ContainedType;
3636+ /// Created a new parser struct based on the expected input type.
2437 fn new(value: Self::Input) -> Self;
2538}
2639···2841/// of concrete parsers.
2942///
3043/// Has blanket implementation for all concrete parsers.
3131-pub trait Operator<Item>: PeekerOperator<Item> + Container {
4444+pub trait Operator: PeekerOperator + Container {
3245 /// Peek the next token in the [Parser] stream. If it
3346 /// matches the pattern specified by the [PeekerOperator]
3447 /// implementation, return something of type `Item` relevant
3548 /// to the token.
3649 ///
3750 /// Return type is the same as that of [PeekerOperator::peek_for].
3838- fn try_next(&self, parser: &mut Parser) -> Option<Item>;
5151+ fn try_next(&self, parser: &mut Parser) -> Option<Self::Item>;
3952}
40534141-impl<T, Item> Operator<Item> for T
5454+impl<T> Operator for T
4255where
4343- T: PeekerOperator<Item> + Container
5656+ T: PeekerOperator + Container
4457{
4545- fn try_next(&self, parser: &mut Parser) -> Option<Item> {
5858+ fn try_next(&self, parser: &mut Parser) -> Option<Self::Item> {
4659 if let Some(itm) = self.peek_for(parser) {
4760 parser.next();
4861 Some(itm)
···5265 }
5366}
54676868+impl IsContainerInput for String {}
6969+impl ContainedType for String {}
7070+impl IsContainerInput for () {}
7171+impl ContainedType for () {}
5572mod exact_match;
5673mod or_exact_match;
5774mod any_str_match;
+3-1
src/parser/parsers/any_str_match.rs
···55/// In particular, match the [Token::Str] variant of
66/// the [Token] enum, and return the inner [String].
77pub struct AnyStrMatch;
88-impl PeekerOperator<String> for AnyStrMatch {
88+impl PeekerOperator for AnyStrMatch {
99+ type Item = String;
1010+911 fn peek_for(&self, parser: &mut Parser) -> Option<String> {
1012 match parser.peek()? {
1113 Token::Str(s) => Some(s),
+3-1
src/parser/parsers/exact_match.rs
···55 /// The string to match to.
66 pub matches: String
77}
88-impl PeekerOperator<String> for ExactMatch {
88+impl PeekerOperator for ExactMatch {
99+ type Item = String;
1010+911 fn peek_for(&self, parser: &mut Parser) -> Option<String> {
1012 if let Some(tok) = parser.peek() {
1113 match tok {
+3-1
src/parser/parsers/is_newline.rs
···4455/// Match a newline.
66pub struct IsNewline;
77-impl PeekerOperator<NewlineToken> for IsNewline {
77+impl PeekerOperator for IsNewline {
88+ type Item = NewlineToken;
99+810 fn peek_for(&self, parser: &mut Parser) -> Option<NewlineToken> {
911 if let Token::Newline(NewlineToken) = parser.peek()? {
1012 Some(NewlineToken)
+7-1
src/parser/parsers/or_exact_match.rs
···66pub struct OrExactMatch {
77 matches: HashSet<String>
88}
99-impl PeekerOperator<String> for OrExactMatch {
99+impl PeekerOperator for OrExactMatch {
1010+ type Item = String;
1111+1012 fn peek_for(&self, parser: &mut Parser) -> Option<String> {
1113 if let Token::Str(s) = parser.peek()? {
1214 if self.matches.contains(&s) {
···1921 }
2022 }
2123}
2424+2525+impl IsContainerInput for Vec<&'static str> {}
2626+impl ContainedType for HashSet<String> {}
2727+2228impl Container for OrExactMatch {
2329 type ContainedType = HashSet<String>;
2430 type Input = Vec<&'static str>;
+21-2
src/parser/subparser.rs
···11-//! [Parser] consume parts of other [Parser]'s tokens.
11+//! [Parsers](Parser) that consume parts of other [Parser]'s tokens.
22+33+use crate::prelude::*;
44+55+/// Functionality to build blanket [Parsers](Parser) using
66+/// a parent [Parser] by consuming its
77+/// tokens based on some pattern.
88+///
99+/// The pattern depends on the generic `C`, which corresponds
1010+/// to a concrete parser. (See [parsers].)
1111+pub trait ConcreteSubparser<C> {
1212+ /// Build the subparser based on the concrete parser.
1313+ fn subparse
1414+ (value: C::Input, parser: &mut Parser) -> Parser
1515+ where
1616+ C: Container;
1717+}
21833-use super::*;1919+mod collect_till;
2020+pub use {
2121+ collect_till::CollectTill,
2222+};
+36
src/parser/subparser/collect_till.rs
···11+use super::*;
22+33+/// Consume tokens into a new parser until the concrete
44+/// parser returns `None`.
55+///
66+/// Said concrete pattern here
77+/// is the generic parameter `Op`.
88+pub struct CollectTill<Op: parsers::Operator>(Op);
99+impl<Op> ConcreteSubparser<Op> for CollectTill<Op>
1010+where
1111+ Op: parsers::Operator
1212+{
1313+ fn subparse
1414+ (value: Op::Input, parser: &mut Parser) -> Parser
1515+ where
1616+ Op: Container
1717+ {
1818+ let op = Op::new(value);
1919+2020+ let mut tokens: Tokens = Tokens::new_empty();
2121+2222+ loop {
2323+ if let Some(_tok) = op.try_next(parser) {
2424+ break;
2525+ } else {
2626+ if let Some(tok) = parser.next() {
2727+ tokens.add_token(tok);
2828+ } else {
2929+ break;
3030+ }
3131+ }
3232+ }
3333+3434+ Parser::new(tokens)
3535+ }
3636+}
···11+use mipl::prelude::*;
22+33+mod common;
44+use common::*;
55+66+#[test]
77+fn test_collect_till_exact_match_subparser() {
88+ let mut parser = setup_space_seps_parser(
99+ "a b c d e f g h"
1010+ );
1111+ let known_subparser = setup_space_seps_parser(
1212+ "a b c d"
1313+ );
1414+1515+ let mut subparser = CollectTill::<ExactMatch>::subparse(
1616+ "e".to_string(),
1717+ &mut parser
1818+ );
1919+2020+ for k in known_subparser {
2121+ if let Token::Newline(NewlineToken) = k {
2222+ break;
2323+ }
2424+ assert_eq!(Some(k), subparser.next())
2525+ }
2626+}
2727+2828+#[test]
2929+fn test_collect_till_is_newline() {
3030+ let mut parser = setup_space_seps_parser(
3131+ "a b\n c d e f g h"
3232+ );
3333+ let known_subparser = setup_space_seps_parser(
3434+ "a b"
3535+ );
3636+3737+ let mut subparser = CollectTill::<IsNewline>::subparse(
3838+ (),
3939+ &mut parser
4040+ );
4141+4242+ for k in known_subparser {
4343+ if let Token::Newline(NewlineToken) = k {
4444+ break;
4545+ }
4646+ assert_eq!(Some(k), subparser.next())
4747+ }
4848+}