Trait nom_supreme::parser_ext::ParserExt
source · [−]pub trait ParserExt<I, O, E>: Parser<I, O, E> + Sized {
Show 24 methods
fn by_ref(&mut self) -> RefParser<'_, Self> { ... }
fn all_consuming(self) -> AllConsuming<Self>
where
I: InputLength,
E: ParseError<I>,
{ ... }
fn complete(self) -> Complete<Self>
where
I: Clone,
E: ParseError<I>,
{ ... }
fn cut(self) -> Cut<Self> { ... }
fn map_res<F, O2, E2>(self, func: F) -> MapRes<Self, F, O, E2>
where
F: FnMut(O) -> Result<O2, E2>,
E: FromExternalError<I, E2>,
I: Clone,
{ ... }
fn map_res_cut<F, O2, E2>(self, func: F) -> MapResCut<Self, F, O, E2>
where
F: FnMut(O) -> Result<O2, E2>,
E: FromExternalError<I, E2>,
I: Clone,
{ ... }
fn opt(self) -> Optional<Self>
where
I: Clone,
{ ... }
fn recognize(self) -> Recognize<Self, O>
where
I: Clone + Slice<RangeTo<usize>> + Offset,
{ ... }
fn with_recognized(self) -> WithRecognized<Self>
where
I: Clone + Slice<RangeTo<usize>> + Offset,
{ ... }
fn value<T: Clone>(self, value: T) -> Value<T, Self, O> { ... }
fn verify<F>(self, verifier: F) -> Verify<Self, F>
where
F: Fn(&O) -> bool,
I: Clone,
E: ParseError<I>,
{ ... }
fn context<C>(self, context: C) -> Context<Self, C>
where
E: ContextError<I, C>,
I: Clone,
C: Clone,
{ ... }
fn terminated<F, O2>(self, terminator: F) -> Terminated<Self, F, O2>
where
F: Parser<I, O2, E>,
{ ... }
fn precedes<F, O2>(self, successor: F) -> Preceded<F, Self, O>
where
F: Parser<I, O2, E>,
{ ... }
fn preceded_by<F, O2>(self, prefix: F) -> Preceded<Self, F, O2>
where
F: Parser<I, O2, E>,
{ ... }
fn opt_precedes<F, O2>(self, successor: F) -> OptionalPreceded<Self, F>
where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
{ ... }
fn opt_preceded_by<F, O2>(self, prefix: F) -> OptionalPreceded<F, Self>
where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
{ ... }
fn delimited_by<D, O2>(self, delimiter: D) -> Delimited<Self, D, O2>
where
D: Parser<I, O2, E>,
{ ... }
fn peek(self) -> Peek<Self>
where
I: Clone,
{ ... }
fn not(self) -> Not<Self, O>
where
I: Clone,
E: ParseError<I>,
{ ... }
fn parse_from_str<'a, T>(self) -> FromStrParser<Self, T>
where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
{ ... }
fn parse_from_str_cut<'a, T>(self) -> FromStrCutParser<Self, T>
where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
{ ... }
fn array(self) -> ArrayParser<Self> { ... }
fn separated_array<F, O2>(
self,
separator: F
) -> SeparatedArrayParser<Self, F, O2>
where
F: Parser<I, O2, E>,
{ ... }
}
Expand description
Additional postfix parser combinators, as a complement to Parser
.
Mostly these are postfix versions of the combinators in nom::combinator
and nom::sequence
, with some additional combinators original to
nom-supreme
.
Compatibility note: it is expected that eventually many of these postfix
methods will eventually be added directly to the Parser
trait. It will
therefore not be considered a compatibility break to remove those methods
from ParserExt
, if they have the same name and signature.
Provided Methods
Borrow a parser. This allows building parser combinators while still
retaining ownership of the original parser. This is necessary because
impl<T: Parser> Parser for &mut T
is impossible due to conflicts
with impl<T: FnMut> Parser for T
.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello");
let mut subparser = parser.by_ref().terminated(tag(", World"));
assert_eq!(subparser.parse("Hello, World!"), Ok(("!", "Hello")));
assert_eq!(
subparser.parse("Hello"),
Err(Err::Error(Error{input: "", code: ErrorKind::Tag}))
);
// We still have ownership of the original parser
assert_eq!(parser.parse("Hello, World!"), Ok((", World!", "Hello")));
assert_eq!(parser.parse("Hello"), Ok(("", "Hello")));
fn all_consuming(self) -> AllConsuming<Self> where
I: InputLength,
E: ParseError<I>,
fn all_consuming(self) -> AllConsuming<Self> where
I: InputLength,
E: ParseError<I>,
Create a parser that must consume all of the input, or else return an error.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").all_consuming();
assert_eq!(parser.parse("Hello"), Ok(("", "Hello")));
assert_eq!(
parser.parse("World"),
Err(Err::Error(Error{input: "World", code: ErrorKind::Tag}))
);
assert_eq!(
parser.parse("Hello World"),
Err(Err::Error(Error{input: " World", code: ErrorKind::Eof}))
);
fn complete(self) -> Complete<Self> where
I: Clone,
E: ParseError<I>,
fn complete(self) -> Complete<Self> where
I: Clone,
E: ParseError<I>,
Create a parser that transforms Incomplete
into Error
.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::streaming::tag;
let mut parser = tag("Hello").complete();
assert_eq!(parser.parse("Hello"), Ok(("", "Hello")));
assert_eq!(
parser.parse("World"),
Err(Err::Error(Error{input: "World", code: ErrorKind::Tag}))
);
assert_eq!(
parser.parse("Hel"),
Err(Err::Error(Error{input: "Hel", code: ErrorKind::Complete}))
);
Create a parser that transforms Error
into Failure
. This will
end the parse immediately, even if there are other branches that
could occur.
Example
use cool_asserts::assert_matches;
use nom::branch::alt;
use nom::character::complete::char;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
use nom_supreme::error::{ErrorTree, BaseErrorKind, Expectation};
let mut parser = alt((
tag("Hello").terminated(char(']')).cut().preceded_by(char('[')),
tag("World").terminated(char(')')).cut().preceded_by(char('(')),
));
assert_matches!(parser.parse("[Hello]"), Ok(("", "Hello")));
assert_matches!(parser.parse("(World)"), Ok(("", "World")));
let branches = assert_matches!(
parser.parse("ABC"),
Err(Err::Error(ErrorTree::Alt(branches))) => branches
);
assert_matches!(
branches.as_slice(),
[
ErrorTree::Base {
kind: BaseErrorKind::Expected(Expectation::Char('[')),
location: "ABC",
},
ErrorTree::Base {
kind: BaseErrorKind::Expected(Expectation::Char('(')),
location: "ABC",
},
]
);
// Notice in this example that there's no error for [Hello]. The cut after
// [ prevented the other branch from being attempted, and prevented earlier
// errors from being retained
assert_matches!(
parser.parse("(Hello)"),
Err(Err::Failure(ErrorTree::Base {
kind: BaseErrorKind::Expected(Expectation::Tag("World")),
location: "Hello)",
}))
);
Create a parser that applies a mapping function func
to the output
of the subparser. Any errors from func
will be transformed into
parse errors via FromExternalError
.
Example
use nom::character::complete::alphanumeric1;
use nom_supreme::parser_ext::ParserExt;
let mut parser = alphanumeric1.map_res(|s: &str| s.parse());
assert_eq!(parser.parse("10 abc"), Ok((" abc", 10)));
assert_eq!(
parser.parse("<===>"),
Err(Err::Error(Error{input: "<===>", code: ErrorKind::AlphaNumeric})),
);
assert_eq!(
parser.parse("abc abc"),
Err(Err::Error(Error{input: "abc abc", code: ErrorKind::MapRes})),
);
fn map_res_cut<F, O2, E2>(self, func: F) -> MapResCut<Self, F, O, E2> where
F: FnMut(O) -> Result<O2, E2>,
E: FromExternalError<I, E2>,
I: Clone,
fn map_res_cut<F, O2, E2>(self, func: F) -> MapResCut<Self, F, O, E2> where
F: FnMut(O) -> Result<O2, E2>,
E: FromExternalError<I, E2>,
I: Clone,
Create a parser that applies a mapping function func
to the output
of the subparser. Any errors from func
will be transformed into
parse failures via FromExternalError
. This will
end the parse immediately, even if there are other branches that
could occur.
Example
use nom::character::complete::alphanumeric1;
use nom_supreme::parser_ext::ParserExt;
let mut parser = alphanumeric1.map_res_cut(|s: &str| s.parse());
assert_eq!(parser.parse("10 abc"), Ok((" abc", 10)));
assert_eq!(
parser.parse("<===>"),
Err(Err::Error(Error{input: "<===>", code: ErrorKind::AlphaNumeric})),
);
assert_eq!(
parser.parse("abc abc"),
Err(Err::Failure(Error{input: "abc abc", code: ErrorKind::MapRes})),
);
Make this parser optional; if it fails to parse, instead it returns
None
with the input in the original position.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
fn parser(input: &str) -> IResult<&str, Option<&str>> {
tag("Hello").opt().parse(input)
}
assert_eq!(parser.parse("Hello, World"), Ok((", World", Some("Hello"))));
assert_eq!(parser.parse("World"), Ok(("World", None)));
let mut parser = tag("Hello").cut().opt();
assert_eq!(
parser.parse("World"),
Err(Err::Failure(Error{input: "World", code: ErrorKind::Tag}))
)
Replace this parser’s output with the entire input that was consumed by the parser.
Example
use nom::character::complete::space1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").delimited_by(space1).recognize();
assert_eq!(parser.parse(" Hello World!"), Ok(("World!", " Hello ")));
assert_eq!(
parser.parse("Hello"),
Err(Err::Error(Error{input: "Hello", code: ErrorKind::Space}))
)
fn with_recognized(self) -> WithRecognized<Self> where
I: Clone + Slice<RangeTo<usize>> + Offset,
fn with_recognized(self) -> WithRecognized<Self> where
I: Clone + Slice<RangeTo<usize>> + Offset,
Return the parsed value, but also return the entire input that was consumed by the parse
Example
use nom::character::complete::space1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").delimited_by(space1).with_recognized();
assert_eq!(parser.parse(" Hello World!"), Ok(("World!", (" Hello ", "Hello"))));
assert_eq!(
parser.parse("Hello"),
Err(Err::Error(Error{input: "Hello", code: ErrorKind::Space}))
)
Replace this parser’s output with a clone of value
every time it
finishes successfully.
Example
use cool_asserts::assert_matches;
use nom::branch::alt;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
use nom_supreme::error::{ErrorTree, BaseErrorKind, Expectation};
let mut parser = alt((
tag("true").value(true),
tag("false").value(false),
));
assert_eq!(parser.parse("true abc").unwrap(), (" abc", true));
assert_eq!(parser.parse("false abc").unwrap(), (" abc", false));
// ErrorTree gives much better error reports for alt and tag.
let choices = assert_matches!(
parser.parse("null"),
Err(Err::Error(ErrorTree::Alt(choices))) => choices
);
assert_matches!(
choices.as_slice(),
[
ErrorTree::Base {
kind: BaseErrorKind::Expected(Expectation::Tag("true")),
location: "null",
},
ErrorTree::Base {
kind: BaseErrorKind::Expected(Expectation::Tag("false")),
location: "null",
},
]
)
Require the output of this parser to pass a verifier function, or else return a parse error.
use nom::character::complete::alpha1;
use nom_supreme::parser_ext::ParserExt;
let mut parser = alpha1.verify(|s: &&str| s.len() == 5);
assert_eq!(parser.parse("Hello"), Ok(("", "Hello")));
assert_eq!(parser.parse("Hello, World"), Ok((", World", "Hello")));
assert_eq!(
parser.parse("abc"),
Err(Err::Error(Error{input: "abc", code: ErrorKind::Verify}))
);
assert_eq!(
parser.parse("abcabcabc"),
Err(Err::Error(Error{input: "abcabcabc", code: ErrorKind::Verify}))
);
assert_eq!(
parser.parse("123"),
Err(Err::Error(Error{input: "123", code: ErrorKind::Alpha}))
);
Add some context to the parser. This context will be added to any
errors that are returned from the parser via ContextError
.
Example
use nom::sequence::separated_pair;
use nom::character::complete::space1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = separated_pair(
tag("Hello").context("hello"),
space1,
tag("World").context("world"),
)
.context("hello world");
assert_eq!(parser.parse("Hello World"), Ok(("", ("Hello", "World"))));
assert_eq!(
parser.parse("Hel"),
Err(Err::Error(VerboseError {errors: vec![
("Hel", VerboseErrorKind::Nom(ErrorKind::Tag)),
("Hel", VerboseErrorKind::Context("hello")),
("Hel", VerboseErrorKind::Context("hello world")),
]}))
);
assert_eq!(
parser.parse("Hello"),
Err(Err::Error(VerboseError {errors: vec![
("", VerboseErrorKind::Nom(ErrorKind::Space)),
("Hello", VerboseErrorKind::Context("hello world")),
]}))
);
assert_eq!(
parser.parse("Hello Wor"),
Err(Err::Error(VerboseError {errors: vec![
("Wor", VerboseErrorKind::Nom(ErrorKind::Tag)),
("Wor", VerboseErrorKind::Context("world")),
("Hello Wor", VerboseErrorKind::Context("hello world")),
]}))
);
fn terminated<F, O2>(self, terminator: F) -> Terminated<Self, F, O2> where
F: Parser<I, O2, E>,
fn terminated<F, O2>(self, terminator: F) -> Terminated<Self, F, O2> where
F: Parser<I, O2, E>,
Add a terminator parser. The terminator will run after this parser, returning any errors, but its output will otherwise be discarded.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").terminated(tag(" World"));
assert_eq!(parser.parse("Hello World!"), Ok(("!", "Hello")));
assert_eq!(
parser.parse("Hello"),
Err(Err::Error(Error{input: "", code: ErrorKind::Tag}))
);
Make this parser precede another one. The successor parser will run after this one succeeds, and the successor’s output will be returned.
Example
use nom::character::complete::digit1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Value: ").precedes(digit1);
assert_eq!(parser.parse("Value: 25;"), Ok((";", "25")));
assert_eq!(
parser.parse("Value: "),
Err(Err::Error(Error{input: "", code: ErrorKind::Digit}))
);
assert_eq!(
parser.parse("25"),
Err(Err::Error(Error{input: "25", code: ErrorKind::Tag}))
);
fn preceded_by<F, O2>(self, prefix: F) -> Preceded<Self, F, O2> where
F: Parser<I, O2, E>,
fn preceded_by<F, O2>(self, prefix: F) -> Preceded<Self, F, O2> where
F: Parser<I, O2, E>,
Make this parser preceded by another one. The prefix
will run first,
and if it succeeds, its output will be discard and this parser will
be run.
Example
use nom::character::complete::digit1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = digit1.preceded_by(tag("Value: "));
assert_eq!(parser.parse("Value: 25;"), Ok((";", "25")));
assert_eq!(
parser.parse("Value: "),
Err(Err::Error(Error{input: "", code: ErrorKind::Digit}))
);
assert_eq!(
parser.parse("25"),
Err(Err::Error(Error{input: "25", code: ErrorKind::Tag}))
);
fn opt_precedes<F, O2>(self, successor: F) -> OptionalPreceded<Self, F> where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
fn opt_precedes<F, O2>(self, successor: F) -> OptionalPreceded<Self, F> where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
Make this parser optionally precede by another one. self
will
run first, and then the successor
will run even if self
returns an
error. Both outputs will be returned. This is functionally equivalent
to self.opt().and(successor)
, but it has the added benefit that if
both parsers return an error, the error from the prefix
will be
retained, rather than discarded.
use cool_asserts::assert_matches;
use nom::character::complete::{digit1, char};
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::error::{ErrorTree, BaseErrorKind, Expectation};
let mut parser = char('-').or(char('+')).opt_precedes(digit1);
assert_matches!(parser.parse("123"), Ok(("", (None, "123"))));
assert_matches!(parser.parse("-123"), Ok(("", (Some('-'), "123"))));
let choices = assert_matches!(
parser.parse("abc"),
Err(Err::Error(ErrorTree::Alt(choices))) => choices,
);
assert_matches!(choices.as_slice(), [
ErrorTree::Base {
location: "abc",
kind: BaseErrorKind::Expected(Expectation::Char('-'))
},
ErrorTree::Base {
location: "abc",
kind: BaseErrorKind::Expected(Expectation::Char('+'))
},
ErrorTree::Base {
location: "abc",
kind: BaseErrorKind::Expected(Expectation::Digit)
},
]);
fn opt_preceded_by<F, O2>(self, prefix: F) -> OptionalPreceded<F, Self> where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
fn opt_preceded_by<F, O2>(self, prefix: F) -> OptionalPreceded<F, Self> where
E: ParseError<I>,
I: Clone,
F: Parser<I, O2, E>,
Make this parser optionally preceded by another one. The prefix
will
run first, and then this parser will run even if the prefix
returned
an error. Both outputs will be returned. This is functionally equivalent
to prefix.opt().and(self)
, but it has the added benefit that if both
parsers return an error, the error from the prefix
will be retained,
rather than discarded.
use cool_asserts::assert_matches;
use nom::character::complete::{digit1, char};
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::error::{ErrorTree, BaseErrorKind, Expectation};
let mut parser = digit1.opt_preceded_by(char('-'));
assert_matches!(parser.parse("123"), Ok(("", (None, "123"))));
assert_matches!(parser.parse("-123"), Ok(("", (Some('-'), "123"))));
let choices = assert_matches!(
parser.parse("abc"),
Err(Err::Error(ErrorTree::Alt(choices))) => choices,
);
assert_matches!(choices.as_slice(), [
ErrorTree::Base {
location: "abc",
kind: BaseErrorKind::Expected(Expectation::Char('-'))
},
ErrorTree::Base {
location: "abc",
kind: BaseErrorKind::Expected(Expectation::Digit)
},
]);
fn delimited_by<D, O2>(self, delimiter: D) -> Delimited<Self, D, O2> where
D: Parser<I, O2, E>,
fn delimited_by<D, O2>(self, delimiter: D) -> Delimited<Self, D, O2> where
D: Parser<I, O2, E>,
Make this parser delimited, requiring a delimiter
as both a prefix and
a suffix. The output of the delimiters is discarded.
Example
use nom::character::complete::{char, digit1};
use nom_supreme::parser_ext::ParserExt;
let mut parser = digit1.delimited_by(char('\''));
assert_eq!(parser.parse("'123' '456'"), Ok((" '456'", "123")));
assert_eq!(
parser.parse("'' ''"),
Err(Err::Error(Error{input: "' ''", code: ErrorKind::Digit}))
);
assert_eq!(
parser.parse("'123 '"),
Err(Err::Error(Error{input: " '", code: ErrorKind::Char}))
);
Make this parser peeking: it runs normally but consumes no input.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").peek();
assert_eq!(parser.parse("Hello World"), Ok(("Hello World", "Hello")));
assert_eq!(
parser.parse("World"),
Err(Err::Error(Error{input: "World", code: ErrorKind::Tag}))
);
fn not(self) -> Not<Self, O> where
I: Clone,
E: ParseError<I>,
fn not(self) -> Not<Self, O> where
I: Clone,
E: ParseError<I>,
Make this parser a negative lookahead: it will succeed if the subparser fails, and fail if the subparser succeeds.
Example
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").not();
assert_eq!(parser.parse("World"), Ok(("World", ())));
assert_eq!(
parser.parse("Hello World"),
Err(Err::Error(Error{input: "Hello World", code: ErrorKind::Not})),
);
fn parse_from_str<'a, T>(self) -> FromStrParser<Self, T> where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
fn parse_from_str<'a, T>(self) -> FromStrParser<Self, T> where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
Create a parser that parses something via FromStr
, using this
parser as a recognizer for the string to pass to
from_str
.
Example
use nom::character::complete::digit1;
use nom_supreme::parser_ext::ParserExt;
let mut parser = digit1.parse_from_str();
assert_eq!(parser.parse("123 abc"), Ok((" abc", 123)));
assert_eq!(
parser.parse("abc"),
Err(Err::Error(Error{input: "abc", code: ErrorKind::Digit})),
);
Parse error example
If the FromStr
parser fails, the error is recoverable from via
FromExternalError
. In general, though, it’s better practice to
ensure your recognizer won’t allow invalid strings to be forwarded to
the FromStr
parser
use std::num::ParseIntError;
use cool_asserts::assert_matches;
use nom::character::complete::alphanumeric1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::error::{ErrorTree, BaseErrorKind};
let mut parser = alphanumeric1.parse_from_str();
assert_matches!(parser.parse("123 abc"), Ok((" abc", 123)));
assert_matches!(
parser.parse("abc"),
Err(Err::Error(ErrorTree::Base{
location: "abc",
kind: BaseErrorKind::External(err),
})) => {
let _err: &ParseIntError = err.downcast_ref().unwrap();
},
);
fn parse_from_str_cut<'a, T>(self) -> FromStrCutParser<Self, T> where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
fn parse_from_str_cut<'a, T>(self) -> FromStrCutParser<Self, T> where
Self: Parser<I, &'a str, E>,
I: Clone,
T: FromStr,
E: FromExternalError<I, T::Err>,
Create a parser that parses something via FromStr
, using this
parser as a recognizer for the string to pass to
from_str
. This parser transforms any errors
from FromStr
into Err::Failure
, which will
end the overall parse immediately, even if there are other branches
that could be tried.
Example
use nom::character::complete::alphanumeric1;
use nom_supreme::parser_ext::ParserExt;
let mut parser = alphanumeric1.parse_from_str_cut();
assert_eq!(parser.parse("123 abc"), Ok((" abc", 123)));
assert_eq!(
parser.parse("<===>"),
Err(Err::Error(Error{input: "<===>", code: ErrorKind::AlphaNumeric})),
);
assert_eq!(
parser.parse("abc"),
Err(Err::Failure(Error{input: "abc", code: ErrorKind::MapRes})),
);
Parse error example
If the FromStr
parser fails, the error is recoverable from via
FromExternalError
. In general, though, it’s better practice to
ensure your recognizer won’t allow invalid strings to be forwarded to
the FromStr
parser
use std::num::ParseIntError;
use cool_asserts::assert_matches;
use nom::character::complete::alphanumeric1;
use nom_supreme::parser_ext::ParserExt;
use nom_supreme::error::{ErrorTree, BaseErrorKind};
let mut parser = alphanumeric1.parse_from_str_cut();
assert_matches!(parser.parse("123 abc"), Ok((" abc", 123)));
assert_matches!(
parser.parse("abc"),
Err(Err::Failure(ErrorTree::Base{
location: "abc",
kind: BaseErrorKind::External(err),
})) => {
let _err: &ParseIntError = err.downcast_ref().unwrap();
},
);
fn array(self) -> ArrayParser<Self>
fn array(self) -> ArrayParser<Self>
Create a parser that parses a fixed-size array by running this parser in a loop.
The returned parser implements Parser
generically over any
const N: usize
, which means it can be used to parse arrays of any
length
Example
use cool_asserts::assert_matches;
use nom::character::complete::digit1;
use nom_supreme::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = digit1
.terminated(tag(", "))
.parse_from_str()
.array();
assert_matches!(parser.parse("123, 456, 789, abc"), Ok(("789, abc", [123, 456])));
assert_matches!(parser.parse("123, 456, 789, abc"), Ok(("abc", [123, 456, 789])));
let res: Result<(&str, [u16; 4]), Err<Error<&str>>> = parser.parse("123, 456, 789, abc");
assert_matches!(
res,
Err(Err::Error(Error{input: "abc", code: ErrorKind::Digit}))
);
Note that this parser does not attach any additional context to the
error in the event of a parser; consider using context
on the item parser or array parser to add additional information about
where in the input there was a parse failure.
fn separated_array<F, O2>(
self,
separator: F
) -> SeparatedArrayParser<Self, F, O2> where
F: Parser<I, O2, E>,
fn separated_array<F, O2>(
self,
separator: F
) -> SeparatedArrayParser<Self, F, O2> where
F: Parser<I, O2, E>,
Create a parser that parses a fixed-size array by running this parser in a loop, parsing a separator in between each element.
The returned parser implements Parser
generically over any
const N: usize
, which means it can be used to parse arrays of any
length
Example
use std::net::{Ipv4Addr, SocketAddrV4};
use cool_asserts::assert_matches;
use nom::character::complete::{char, digit1};
use nom_supreme::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = digit1
.parse_from_str()
.separated_array(char('.'))
.map(Ipv4Addr::from)
.terminated(char(':'))
.and(digit1.parse_from_str())
.map(|(ip, port)| SocketAddrV4::new(ip, port));
let (_tail, socket_addr) = parser.parse("192.168.0.1:80").unwrap();
assert_eq!(socket_addr.ip().octets(), [192, 168, 0, 1]);
assert_eq!(socket_addr.port(), 80);
assert_matches!(
parser.parse("192.168.0.abc:80"),
Err(Err::Error(Error{input: "abc:80", code: ErrorKind::Digit})),
);
assert_matches!(
parser.parse("192.168.0.1"),
Err(Err::Error(Error{input: "", code: ErrorKind::Char})),
);
assert_matches!(
parser.parse("192.168.0.1000:80"),
Err(Err::Error(Error{input: "1000:80", code: ErrorKind::MapRes})),
);
assert_matches!(
parser.parse("192.168.10abc"),
Err(Err::Error(Error{input: "abc", code: ErrorKind::Char})),
);
Note that this parser does not attach any additional context to the
error in the event of a parser; consider using context
on the item, separator, or array parsers to add additional information
about where in the input there was a parse failure.