tamer: xir::tree::parse: ParseStatus and Parsed

The old Parsed was renamed to ParseStatus to be used by Parser, and Parser
converts it into Parsed, which has the same variants as it did before and
has all but the Done variant, since it's not possible for Parser to yield
it.

DEV-11268
main
Mike Gerwitz 2021-12-10 16:51:53 -05:00
parent 9facc26b4f
commit c6d6f44bcb
3 changed files with 46 additions and 16 deletions

View File

@ -1060,7 +1060,7 @@ pub fn attr_parser_from<'a>(
AttrParserState::parser(toks).filter_map(|parsed| match parsed {
Ok(Parsed::Object(attr)) => Some(Ok(attr)),
Ok(Parsed::Incomplete | Parsed::Done) => None,
Ok(Parsed::Incomplete) => None,
Err(x) => Some(Err(x.into())),
})
}

View File

@ -22,7 +22,7 @@
use crate::{
span::Span,
xir::{
tree::parse::{ParseState, ParseStateResult, Parsed},
tree::parse::{ParseState, ParseStateResult, ParseStatus},
QName, Token,
},
};
@ -52,17 +52,17 @@ impl ParseState for AttrParserState {
use AttrParserState::*;
match (take(self), tok) {
(Empty, Token::AttrEnd(_)) => return Ok(Parsed::Done),
(Empty, Token::AttrEnd(_)) => return Ok(ParseStatus::Done),
(Empty, Token::AttrName(name, span)) => {
*self = Name(name, span);
Ok(Parsed::Incomplete)
Ok(ParseStatus::Incomplete)
}
(Empty, invalid) => Err(AttrParseError::AttrNameExpected(invalid)),
(Name(name, nspan), Token::AttrValue(value, vspan)) => {
Ok(Parsed::Object(Attr::new(name, value, (nspan, vspan))))
Ok(ParseStatus::Object(Attr::new(name, value, (nspan, vspan))))
}
(Name(name, nspan), invalid) => {
@ -163,14 +163,14 @@ mod test {
// and so we are awaiting a value.
assert_eq!(
sut.parse_token(Token::AttrName(attr, *S)),
Ok(Parsed::Incomplete)
Ok(ParseStatus::Incomplete)
);
// Once we have a value,
// an Attr can be emitted.
assert_eq!(
sut.parse_token(Token::AttrValue(val, *S2)),
Ok(Parsed::Object(expected))
Ok(ParseStatus::Object(expected))
);
}
@ -184,7 +184,7 @@ mod test {
// the token stream.
assert_eq!(
sut.parse_token(Token::AttrName(attr, *S)),
Ok(Parsed::Incomplete)
Ok(ParseStatus::Incomplete)
);
// But we provide something else unexpected.
@ -210,7 +210,7 @@ mod test {
let expected = Attr::new(attr, recover, (*S, *S2));
assert_eq!(
sut.parse_token(Token::AttrValue(recover, *S2)),
Ok(Parsed::Object(expected))
Ok(ParseStatus::Object(expected))
);
// Finally, we should now be in an accepting state.
@ -221,7 +221,7 @@ mod test {
fn yields_none_on_attr_end() {
let mut sut = AttrParserState::default();
assert_eq!(sut.parse_token(Token::AttrEnd(*S)), Ok(Parsed::Done));
assert_eq!(sut.parse_token(Token::AttrEnd(*S)), Ok(ParseStatus::Done));
assert!(sut.is_accepting());
}
}

View File

@ -95,7 +95,7 @@ pub trait ParseState: Default {
/// Result of applying a [`Token`] to a [`ParseState`].
pub type ParseStateResult<S> =
Result<Parsed<<S as ParseState>::Object>, <S as ParseState>::Error>;
Result<ParseStatus<<S as ParseState>::Object>, <S as ParseState>::Error>;
/// A streaming parser defined by a [`ParseState`] with exclusive
/// mutable access to an underlying [`TokenStream`].
@ -167,8 +167,9 @@ impl<'a, S: ParseState, I: TokenStream> Iterator for Parser<'a, S, I> {
self.last_span = Some(tok.span());
match self.state.parse_token(tok) {
Ok(Parsed::Done) => None,
parsed => Some(parsed.map_err(ParseError::from)),
Ok(ParseStatus::Done) => None,
Ok(parsed) => Some(Ok(parsed.into())),
Err(e) => Some(Err(e.into())),
}
}
}
@ -252,7 +253,7 @@ impl<'a, S: ParseState, I: TokenStream> From<&'a mut I> for Parser<'a, S, I> {
/// Result of a parsing operation.
#[derive(Debug, PartialEq, Eq)]
pub enum Parsed<T> {
pub enum ParseStatus<T> {
/// Additional tokens are needed to complete parsing of the next object.
Incomplete,
@ -266,11 +267,40 @@ pub enum Parsed<T> {
/// Parsing is complete.
///
/// This should cause an iterator to yield [`None`].
/// If a parser is a combination of multiple [`ParserState`]s,
/// If a parser is a combination of multiple [`ParseState`]s,
/// this should transition to the next appropriate state.
Done,
}
/// Result of a parsing operation.
///
/// Whereas [`ParseStatus`] is used by [`ParseState`] to influence parser
/// operation,
/// this type is public-facing and used by [`Parser`].
#[derive(Debug, PartialEq, Eq)]
pub enum Parsed<T> {
/// Additional tokens are needed to complete parsing of the next object.
Incomplete,
/// Parsing of an object is complete.
///
/// This does not indicate that the parser is complete,
/// as more objects may be able to be emitted.
Object(T),
}
impl<T> From<ParseStatus<T>> for Parsed<T> {
fn from(status: ParseStatus<T>) -> Self {
match status {
ParseStatus::Incomplete => Parsed::Incomplete,
ParseStatus::Object(x) => Parsed::Object(x),
ParseStatus::Done => {
unreachable!("Done status must be filtered by Parser")
}
}
}
}
#[cfg(test)]
pub mod test {
use std::assert_matches::assert_matches;
@ -305,7 +335,7 @@ pub mod test {
_ => {}
}
Ok(Parsed::Object(tok))
Ok(ParseStatus::Object(tok))
}
fn is_accepting(&self) -> bool {