Macro konst::parser_method

source ·
macro_rules! parser_method {
    ($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)* ) => { ... };
}
Available on crate feature parsing_proc only.
Expand description

Calls a Parser method with many alternative string literals.

If any of the literals match, the parser is mutated accordingly, otherwise the parser is left untouched.

§Syntax

The general syntax for this macro is parser_method!{ <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:

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 (constants 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},
    parser_method, unwrap_ctx,
};

#[derive(Debug, PartialEq)]
enum Color {
    Red,
    Blue,
    Green,
}

impl Color {
    pub const fn try_parse(mut parser: Parser<'_>) -> ParseValueResult<'_, Color> {
        parser_method!{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(&"could not parse Color")),
        }
    }
}

const COLORS: [Color; 4] = {
    let parser = Parser::new("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},
    parser_method, unwrap_ctx,
};

{
    let mut parser = Parser::new("baz_foo_bar_foo");

    fn find(parser: &mut Parser<'_>) -> u32 {
        let before = parser.remainder();
        parser_method!{*parser, find_skip;
            "foo" => 0,
            "bar" => 1,
            "baz" => 2,
            _ => {
                assert_eq!(before, parser.remainder());
                3
            }
        }
    }

    assert_eq!(find(&mut parser), 2);
    assert_eq!(parser.remainder(), "_foo_bar_foo");
     
    assert_eq!(find(&mut parser), 0);
    assert_eq!(parser.remainder(), "_bar_foo");
     
    assert_eq!(find(&mut parser), 1);
    assert_eq!(parser.remainder(), "_foo");
     
    assert_eq!(find(&mut parser), 0);
    assert_eq!(parser.remainder(), "");
     
    assert_eq!(find(&mut parser), 3);
    assert_eq!(parser.remainder(), "");
}
{
    let mut parser = Parser::new("foo_bar_foo_baz");

    fn rfind(parser: &mut Parser<'_>) -> u32 {
        parser_method!{*parser, rfind_skip;
            "foo" => 0,
            "bar" => 1,
            "baz" => 2,
            _ => 3,
        }
    }

    assert_eq!(rfind(&mut parser), 2);
    assert_eq!(parser.remainder(), "foo_bar_foo_");
     
    assert_eq!(rfind(&mut parser), 0);
    assert_eq!(parser.remainder(), "foo_bar_");
     
    assert_eq!(rfind(&mut parser), 1);
    assert_eq!(parser.remainder(), "foo_");
     
    assert_eq!(rfind(&mut parser), 0);
    assert_eq!(parser.remainder(), "");
     
    assert_eq!(rfind(&mut parser), 3);
    assert_eq!(parser.remainder(), "");
}


§Trimming

use konst::{
    parsing::{Parser, ParseValueResult},
    parser_method, unwrap_ctx,
};

{
    let mut parser = Parser::new("foobarhellofoobar");
    parser_method!{parser, trim_start_matches; "foo" | "bar" }
    assert_eq!(parser.remainder(), "hellofoobar");
}
{
    let mut parser = Parser::new("foobarhellofoobar");
    parser_method!{parser, trim_end_matches; "foo" | "bar" }
    assert_eq!(parser.remainder(), "foobarhello");
}
{
    let mut parser = Parser::new("foobar");
    // Empty string literals make trimming finish when the previous patterns didn't match,
    // so the "bar" pattern doesn't do anything here
    parser_method!{parser, trim_start_matches; "foo" | "" | "bar" }
    assert_eq!(parser.remainder(), "bar");
}