pub trait Stateful<S> {
type Output;
// Required methods
fn parse(self, value: S) -> ParseResult<Self, S>
where Self: Sized;
fn done(self) -> Self::Output
where Self: Sized;
// Provided method
fn boxable(self) -> BoxableParser<Self>
where Self: Sized { ... }
}Expand description
A trait for stateful parsers.
Stateful parsers are typically constructed by calling the init method of a stateless parser,
for example:
let stateless = character(char::is_alphanumeric).star(String::new);
let stateful = stateless.init();Here, stateless is a Committed<&str,Output=String>, and stateful is a Stateful<&str,Output=String>.
The reason for distinguishing between stateful and stateless parsers is that stateless parsers are usually copyable, whereas stateful parsers are usually not (they may, for example, have created and partially filled some buffers). Copying parsers is quite common, for example:
fn mk_err() -> Result<char,String> { Err(String::from("Expecting a digit")) }
let DIGIT = character(char::is_numeric).map(Ok).or_emit(mk_err);
let TWO_DIGITS = DIGIT.try_and_then_try(DIGIT);
match TWO_DIGITS.init().parse("123") {
Done("3",result) => assert_eq!(result,Ok(('1','2'))),
_ => panic!("Can't happen"),
}Required Associated Types§
Required Methods§
Sourcefn parse(self, value: S) -> ParseResult<Self, S>where
Self: Sized,
fn parse(self, value: S) -> ParseResult<Self, S>where
Self: Sized,
Provides data to the parser.
If parser: Stateful<S,Output=T>, then parser.parse(data) either:
- returns
Done(rest, result)whererest: Sis any remaining input, andresult: Tis the parsed output, or - returns
Continue(rest,parsing)whereparsing: Selfis the new state of the parser.
For example:
let parser = character(char::is_alphabetic).star(String::new);
let stateful = parser.init();
match stateful.parse("abc") {
Continue("",parsing) => match parsing.parse("def!") {
Done("!",result) => assert_eq!(result,"abcdef"),
_ => panic!("can't happen"),
},
_ => panic!("can't happen"),
}Note that parser.parse(data) consumes both the parser and the data. In particular,
the parser is no longer available, so the following does not typecheck:
let parser = character(char::is_alphabetic).star(String::new);
let stateful = parser.init();
stateful.parse("abc");
stateful.parse("def!");This helps with parser safety, as it stops a client from calling parse after a
a stateful parser has finished.
Sourcefn done(self) -> Self::Outputwhere
Self: Sized,
fn done(self) -> Self::Outputwhere
Self: Sized,
Tells the parser that it will not receive any more data.
If parser: Stateful<S,Output=T>, then parser.done() returns a result of type T
for example:
let parser = character(char::is_alphabetic).star(String::new);
let stateful = parser.init();
match stateful.parse("abc") {
Continue("",parsing) => match parsing.parse("def") {
Continue("",parsing) => assert_eq!(parsing.done(),"abcdef"),
_ => panic!("can't happen"),
},
_ => panic!("can't happen"),
}Note that parser.done() consumes the parser. In particular,
the parser is no longer available, so the following does not typecheck:
let parser = character(char::is_alphabetic).star(String::new);
let stateful = parser.init();
stateful.done();
stateful.parse("def!");This helps with parser safety, as it stops a client from calling parse after a
a stateful parser has finished.
Provided Methods§
Sourcefn boxable(self) -> BoxableParser<Self>where
Self: Sized,
fn boxable(self) -> BoxableParser<Self>where
Self: Sized,
Make this parser boxable.