Trait nom_supreme::parser_ext::ParserExt [−][src]
pub trait ParserExt<I, O, E>: Parser<I, O, E> + Sized {
Show 22 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(self, context: &'static str) -> Context<Self>
where
E: ContextError<I>,
I: 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 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<&'a str, &'a str, E>,
T: FromStr,
E: FromExternalError<&'a str, 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 nom_supreme::parser_ext::ParserExt;
use nom_supreme::tag::complete::tag;
let mut parser = tag("Hello").cut();
assert_eq!(parser.parse("Hello"), Ok(("", "Hello")));
assert_eq!(
parser.parse("World"),
Err(Err::Failure(Error{input: "World", code: ErrorKind::Tag}))
);
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 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 err = parser.parse("null").unwrap_err();
let choices = match err {
Err::Error(ErrorTree::Alt(choices)) => choices,
_ => panic!("Unexpected error {:?}", err)
};
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 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<&'a str, &'a str, E>,
T: FromStr,
E: FromExternalError<&'a str, T::Err>,
fn parse_from_str_cut<'a, T>(self) -> FromStrCutParser<Self, T> where
Self: Parser<&'a str, &'a str, E>,
T: FromStr,
E: FromExternalError<&'a str, 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.