Minimal Imperative Parsing Library | https://docs.rs/mipl

improve naming and item visibility in prelude

+59 -58
+6 -1
src/lib.rs
··· 13 }, 14 parser::{ 15 *, 16 - parsers::*, 17 subparser::* 18 } 19 };
··· 13 }, 14 parser::{ 15 *, 16 + concrete_parser::{ 17 + self, 18 + ConcreteParser, 19 + ContainerCp, 20 + list::* 21 + }, 22 subparser::* 23 } 24 };
+7 -14
src/parser.rs
··· 8 tokens: Peekable<Tokens> 9 } 10 impl Parser{ 11 /// Create a new [Parser] from tokens. 12 pub fn new(tokens: Tokens) -> Parser { 13 Parser { tokens: tokens.peekable() } ··· 32 } 33 } 34 35 - /// Peeking functionality. 36 - pub trait Peeker { 37 - /// Look up the next token in the stream 38 - /// without consuming it. 39 - fn peek(&mut self) -> Option<Token>; 40 - } 41 - 42 - impl Peeker for Parser { 43 - fn peek(&mut self) -> Option<Token> { 44 - self.tokens.peek().cloned() 45 - } 46 - } 47 - 48 - pub mod parsers; 49 pub mod subparser;
··· 8 tokens: Peekable<Tokens> 9 } 10 impl Parser{ 11 + /// Look up the next token in the stream 12 + /// without consuming it. 13 + pub fn peek(&mut self) -> Option<Token> { 14 + self.tokens.peek().cloned() 15 + } 16 + 17 /// Create a new [Parser] from tokens. 18 pub fn new(tokens: Tokens) -> Parser { 19 Parser { tokens: tokens.peekable() } ··· 38 } 39 } 40 41 + pub mod concrete_parser; 42 pub mod subparser;
+25 -22
src/parser/parsers.rs src/parser/concrete_parser.rs
··· 19 } 20 21 /// The peeking functionality of concrete parsers. 22 - pub trait PeekerOperator { 23 /// The type of the elements. 24 type Item: PeekerItem; 25 ··· 28 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token>; 29 30 /// Peek for the next element. Implemented based on 31 - /// [PeekerOperator::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)? ··· 36 } 37 } 38 39 - /// Marks container input types at the trait-level. 40 - pub trait IsContainerInput {} 41 - /// Marks container types at the trait-level. 42 pub trait ContainedType {} 43 44 /// Interface for containing data in the concrete parser structs. 45 - pub trait Container { 46 /// The type the concrete parsers are constructed from. 47 - type Input: IsContainerInput; 48 /// The type the concrete parser structs contain. 49 type ContainedType: ContainedType; 50 ··· 54 fn new(value: Self::Input) -> Self; 55 } 56 57 - /// Along with [PeekerOperator], defines the core functionality 58 /// of concrete parsers. 59 /// 60 /// Has blanket implementation for all concrete parsers. 61 - pub trait Operator: PeekerOperator + Container { 62 /// Peek the next token in the [Parser] stream. If it 63 - /// satisfies the criteria as specified by the [PeekerOperator] 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 - /// [Operator::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 [PeekerOperator::peek_for]. 73 fn try_next(&self, parser: &mut Parser) -> Option<Self::Item> { 74 Self::Item::from_tok( 75 self.try_next_token(parser)? ··· 77 } 78 } 79 80 - impl<T> Operator for T 81 where 82 - T: PeekerOperator + Container 83 { 84 fn try_next_token(&self, parser: &mut Parser) -> Option<Token> { 85 if let Some(tok) = self.peek_for_token(parser) { ··· 91 } 92 } 93 94 - impl IsContainerInput for String {} 95 impl ContainedType for String {} 96 97 - impl IsContainerInput for () {} 98 impl ContainedType for () {} 99 100 mod exact_match; 101 mod or_exact_match; 102 mod any_str_match; 103 mod is_newline; 104 - pub use { 105 - exact_match::ExactMatch, 106 - or_exact_match::OrExactMatch, 107 - any_str_match::AnyStrMatch, 108 - is_newline::IsNewline, 109 - };
··· 19 } 20 21 /// The peeking functionality of concrete parsers. 22 + pub trait Peeker { 23 /// The type of the elements. 24 type Item: PeekerItem; 25 ··· 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)? ··· 36 } 37 } 38 39 + /// Marks [ContainerCp] input types at the trait-level. 40 + pub trait IsContainerCpInput {} 41 + /// Marks [ContainerCp] types at the trait-level. 42 pub trait ContainedType {} 43 44 /// Interface for containing data in the concrete parser structs. 45 + pub 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 ··· 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. 61 + pub 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)? ··· 77 } 78 } 79 80 + impl<T> ConcreteParser for T 81 where 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) { ··· 91 } 92 } 93 94 + impl IsContainerCpInput for String {} 95 impl ContainedType for String {} 96 97 + impl IsContainerCpInput for () {} 98 impl ContainedType for () {} 99 100 mod exact_match; 101 mod or_exact_match; 102 mod any_str_match; 103 mod is_newline; 104 + /// All concrete parsers. 105 + pub mod list { 106 + pub use super::{ 107 + exact_match::ExactMatch, 108 + or_exact_match::OrExactMatch, 109 + any_str_match::AnyStrMatch, 110 + is_newline::IsNewline, 111 + }; 112 + }
+2 -2
src/parser/parsers/any_str_match.rs src/parser/concrete_parser/any_str_match.rs
··· 5 /// In particular, match the [Token::Str] variant of 6 /// the [Token] enum, and return the inner [String]. 7 pub struct AnyStrMatch; 8 - impl PeekerOperator for AnyStrMatch { 9 type Item = String; 10 11 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 15 } 16 } 17 } 18 - impl Container for AnyStrMatch { 19 type Input = (); 20 type ContainedType = (); 21
··· 5 /// In particular, match the [Token::Str] variant of 6 /// the [Token] enum, and return the inner [String]. 7 pub struct AnyStrMatch; 8 + impl Peeker for AnyStrMatch { 9 type Item = String; 10 11 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 15 } 16 } 17 } 18 + impl ContainerCp for AnyStrMatch { 19 type Input = (); 20 type ContainedType = (); 21
+2 -2
src/parser/parsers/exact_match.rs src/parser/concrete_parser/exact_match.rs
··· 5 /// The string to match to. 6 pub matches: String 7 } 8 - impl PeekerOperator for ExactMatch { 9 type Item = String; 10 11 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 25 } 26 } 27 } 28 - impl Container for ExactMatch { 29 type Input = String; 30 type ContainedType = String; 31
··· 5 /// The string to match to. 6 pub matches: String 7 } 8 + impl Peeker for ExactMatch { 9 type Item = String; 10 11 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 25 } 26 } 27 } 28 + impl ContainerCp for ExactMatch { 29 type Input = String; 30 type ContainedType = String; 31
+2 -2
src/parser/parsers/is_newline.rs src/parser/concrete_parser/is_newline.rs
··· 14 15 /// Match a newline. 16 pub struct IsNewline; 17 - impl PeekerOperator for IsNewline { 18 type Item = NewlineToken; 19 20 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 24 } 25 } 26 } 27 - impl Container for IsNewline { 28 type ContainedType = (); 29 type Input = (); 30
··· 14 15 /// Match a newline. 16 pub struct IsNewline; 17 + impl Peeker for IsNewline { 18 type Item = NewlineToken; 19 20 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 24 } 25 } 26 } 27 + impl ContainerCp for IsNewline { 28 type ContainedType = (); 29 type Input = (); 30
+3 -3
src/parser/parsers/or_exact_match.rs src/parser/concrete_parser/or_exact_match.rs
··· 6 pub struct OrExactMatch { 7 matches: HashSet<String> 8 } 9 - impl PeekerOperator for OrExactMatch { 10 type Item = String; 11 12 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 22 } 23 } 24 25 - impl IsContainerInput for Vec<&'static str> {} 26 impl ContainedType for HashSet<String> {} 27 28 - impl Container for OrExactMatch { 29 type ContainedType = HashSet<String>; 30 type Input = Vec<&'static str>; 31
··· 6 pub struct OrExactMatch { 7 matches: HashSet<String> 8 } 9 + impl Peeker for OrExactMatch { 10 type Item = String; 11 12 fn peek_for_token(&self, parser: &mut Parser) -> Option<Token> { ··· 22 } 23 } 24 25 + impl IsContainerCpInput for Vec<&'static str> {} 26 impl ContainedType for HashSet<String> {} 27 28 + impl ContainerCp for OrExactMatch { 29 type ContainedType = HashSet<String>; 30 type Input = Vec<&'static str>; 31
+2 -2
src/parser/subparser.rs
··· 7 /// tokens based on some pattern. 8 /// 9 /// The pattern depends on the generic `C`, which corresponds 10 - /// to a concrete parser. (See [parsers].) 11 pub trait ConcreteSubparser<C> { 12 /// Build the subparser based on the concrete parser. 13 fn subparse 14 (value: C::Input, parser: &mut Parser) -> Parser 15 where 16 - C: Container; 17 } 18 19 mod collect_till;
··· 7 /// tokens based on some pattern. 8 /// 9 /// The pattern depends on the generic `C`, which corresponds 10 + /// to a concrete parser. (See [concrete_parser].) 11 pub trait ConcreteSubparser<C> { 12 /// Build the subparser based on the concrete parser. 13 fn subparse 14 (value: C::Input, parser: &mut Parser) -> Parser 15 where 16 + C: concrete_parser::ContainerCp; 17 } 18 19 mod collect_till;
+4 -4
src/parser/subparser/collect_till.rs
··· 1 - use super::*; 2 3 /// Consume tokens into a new parser until the concrete 4 /// parser returns something. Stops when it hits `Some(_)`. 5 /// 6 /// Said concrete pattern here is provided by 7 /// the generic parameter `Op`. 8 - pub struct CollectTill<Op: parsers::Operator>(Op); 9 impl<Op> ConcreteSubparser<Op> for CollectTill<Op> 10 where 11 - Op: parsers::Operator 12 { 13 fn subparse 14 (value: Op::Input, parser: &mut Parser) -> Parser 15 where 16 - Op: Container 17 { 18 let op = Op::new(value); 19
··· 1 + use crate::prelude::*; 2 3 /// Consume tokens into a new parser until the concrete 4 /// parser returns something. Stops when it hits `Some(_)`. 5 /// 6 /// Said concrete pattern here is provided by 7 /// the generic parameter `Op`. 8 + pub struct CollectTill<Op: ConcreteParser>(Op); 9 impl<Op> ConcreteSubparser<Op> for CollectTill<Op> 10 where 11 + Op: ConcreteParser 12 { 13 fn subparse 14 (value: Op::Input, parser: &mut Parser) -> Parser 15 where 16 + Op: concrete_parser::ContainerCp 17 { 18 let op = Op::new(value); 19
+4 -4
src/parser/subparser/collect_while.rs
··· 1 - use super::*; 2 3 /// Consume tokens into a new parser while the concrete 4 /// parser returns something. Stop consuming if it returns ··· 6 /// 7 /// Said concrete pattern here is provided by 8 /// the generic parameter `Op`. 9 - pub struct CollectWhile<Op: parsers::Operator>(Op); 10 impl<Op> ConcreteSubparser<Op> for CollectWhile<Op> 11 where 12 - Op: parsers::Operator 13 { 14 fn subparse 15 (value: <Op>::Input, parser: &mut Parser) -> Parser 16 where 17 - Op: Container 18 { 19 let op = Op::new(value); 20
··· 1 + use crate::prelude::*; 2 3 /// Consume tokens into a new parser while the concrete 4 /// parser returns something. Stop consuming if it returns ··· 6 /// 7 /// Said concrete pattern here is provided by 8 /// the generic parameter `Op`. 9 + pub struct CollectWhile<Op: ConcreteParser>(Op); 10 impl<Op> ConcreteSubparser<Op> for CollectWhile<Op> 11 where 12 + Op: ConcreteParser 13 { 14 fn subparse 15 (value: <Op>::Input, parser: &mut Parser) -> Parser 16 where 17 + Op: concrete_parser::ContainerCp 18 { 19 let op = Op::new(value); 20
+2 -2
tests/test_parsers.rs
··· 7 fn test_exact_match() { 8 let mut parser = setup_space_seps_parser("lorem ipsum"); 9 10 - let ipsum_parser = parsers::ExactMatch{ 11 matches: String::from("ipsum") 12 }; 13 parser.next(); ··· 18 fn test_exact_match_try_next_advance_token() { 19 let mut parser = setup_space_seps_parser("lorem ipsum"); 20 21 - let ipsum_parser = parsers::ExactMatch{ 22 matches: String::from("lorem") 23 }; 24 ipsum_parser.try_next(&mut parser);
··· 7 fn test_exact_match() { 8 let mut parser = setup_space_seps_parser("lorem ipsum"); 9 10 + let ipsum_parser = ExactMatch{ 11 matches: String::from("ipsum") 12 }; 13 parser.next(); ··· 18 fn test_exact_match_try_next_advance_token() { 19 let mut parser = setup_space_seps_parser("lorem ipsum"); 20 21 + let ipsum_parser = ExactMatch{ 22 matches: String::from("lorem") 23 }; 24 ipsum_parser.try_next(&mut parser);