Macro konst::parse_any [−][src]
macro_rules! parse_any { ($place : expr, find_skip ; $($branches : tt) *) => { ... }; ($place : expr, rfind_skip ; $($branches : tt) *) => { ... }; ($place : expr, strip_prefix ; $($branches : tt) *) => { ... }; ($place : expr, strip_suffix ; $($branches : tt) *) => { ... }; ($place : expr, trim_start_matches ; $($branches : tt) *) => { ... }; ($place : expr, trim_end_matches ; $($branches : tt) *) => { ... }; ($place : expr, $unknown_method : ident ; $($branches : tt) *) => { ... }; }
parsing
only.Expand description
Calls a Parser
method with many alternative string literals.
If any of the literals match, the parser is mutated accordingly, otherwise it keeps the unparsed bytes to parse them again.
Syntax
The general syntax for this macro is
parse_any!{ <parser_expression> , <method_name> => <branches> }
Where <parser_expression>
is an expression (of Parser
type) that can be assigned into.
Where <method_name>
is the name of one of the Parser
methods usable in this macro:
-
find_skip
andrfind_skip
: use the match-like syntax, running the branch of the first pattern that matches. example -
strip_prefix
andstrip_suffix
: use the match-like syntax, running the branch of the first pattern that matches. example -
trim_start_matches
andtrim_end_matches
: use the pattern-only syntax, trimming the string while any pattern matches. example
Where <branches>
can be either of these, depending on the <method_name>
:
-
A match-like syntax: A comma separated sequence of
<patterns> => <expression>
branches, the last branch must be_ => <expression>
. -
Just the patterns:
<patterns>
.
Where <patterns>
can be be any amount of |
-separated string literals
(const
ants don’t work here), or _
.
Note that passing a macro that expands to a literal doesn’t work here,
concat
and stringify
are special cased to work.
Example
Parsing enum
use konst::{ parsing::{Parser, ParseValueResult}, parse_any, unwrap_ctx, }; #[derive(Debug, PartialEq)] enum Color { Red, Blue, Green, } impl Color { pub const fn try_parse(mut parser: Parser<'_>) -> ParseValueResult<'_, Color> { parse_any!{parser, strip_prefix; "Red"|"red" => Ok((Color::Red, parser)), "Blue"|"blue" => Ok((Color::Blue, parser)), "Green"|"green" => Ok((Color::Green, parser)), _ => Err(parser.into_other_error()), } } } const COLORS: [Color; 4] = { let parser = Parser::from_str("BlueRedGreenGreen"); let (c0, parser) = unwrap_ctx!(Color::try_parse(parser)); let (c1, parser) = unwrap_ctx!(Color::try_parse(parser)); let (c2, parser) = unwrap_ctx!(Color::try_parse(parser)); let (c3, _ ) = unwrap_ctx!(Color::try_parse(parser)); [c0, c1, c2, c3] }; assert_eq!(COLORS, [Color::Blue, Color::Red, Color::Green, Color::Green])
find_skip
use konst::{ parsing::{Parser, ParseValueResult}, parse_any, unwrap_ctx, }; { let mut parser = Parser::from_str("baz_foo_bar_foo"); fn find(parser: &mut Parser<'_>) -> u32 { let before = parser.bytes(); parse_any!{*parser, find_skip; "foo" => 0, "bar" => 1, "baz" => 2, _ => { assert_eq!(before, parser.bytes()); 3 } } } assert_eq!(find(&mut parser), 2); assert_eq!(parser.bytes(), "_foo_bar_foo".as_bytes()); assert_eq!(find(&mut parser), 0); assert_eq!(parser.bytes(), "_bar_foo".as_bytes()); assert_eq!(find(&mut parser), 1); assert_eq!(parser.bytes(), "_foo".as_bytes()); assert_eq!(find(&mut parser), 0); assert_eq!(parser.bytes(), "".as_bytes()); assert_eq!(find(&mut parser), 3); assert_eq!(parser.bytes(), "".as_bytes()); } { let mut parser = Parser::from_str("foo_bar_foo_baz"); fn rfind(parser: &mut Parser<'_>) -> u32 { parse_any!{*parser, rfind_skip; "foo" => 0, "bar" => 1, "baz" => 2, _ => 3, } } assert_eq!(rfind(&mut parser), 2); assert_eq!(parser.bytes(), "foo_bar_foo_".as_bytes()); assert_eq!(rfind(&mut parser), 0); assert_eq!(parser.bytes(), "foo_bar_".as_bytes()); assert_eq!(rfind(&mut parser), 1); assert_eq!(parser.bytes(), "foo_".as_bytes()); assert_eq!(rfind(&mut parser), 0); assert_eq!(parser.bytes(), "".as_bytes()); assert_eq!(rfind(&mut parser), 3); assert_eq!(parser.bytes(), "".as_bytes()); }
Trimming
use konst::{ parsing::{Parser, ParseValueResult}, parse_any, unwrap_ctx, }; { let mut parser = Parser::from_str("foobarhellofoobar"); parse_any!{parser, trim_start_matches; "foo" | "bar" } assert_eq!(parser.bytes(), "hellofoobar".as_bytes()); } { let mut parser = Parser::from_str("foobarhellofoobar"); parse_any!{parser, trim_end_matches; "foo" | "bar" } assert_eq!(parser.bytes(), "foobarhello".as_bytes()); } { let mut parser = Parser::from_str("foobar"); // Empty string literals make trimming finish when the previous patterns didn't match, // so the "bar" pattern doesn't do anything here parse_any!{parser, trim_start_matches; "foo" | "" | "bar" } assert_eq!(parser.bytes(), "bar".as_bytes()); }