tamer: xir::tree::attr_parser_from: Do not take ownership over iter
The previous implementation took ownership over the provided iterator, which was an oversight, considering that this is intended to be used in contexts where doing so is not possible. A good example where isolated test cases aren't necessarily painting the correct picture. `scan` takes owned values, so this instead uses the same parsing method as `parse_attrs`, but using a `FromFn` iterator to avoid having to create a whole new iterator type. This will work well so long as we don't need to store the type returned by this (while also wanting to avoid boxing). DEV-11062main
parent
428d508be4
commit
1f01833d30
|
@ -196,7 +196,7 @@
|
|||
|
||||
use super::{AttrValue, QName, Text, Token, TokenResultStream, TokenStream};
|
||||
use crate::span::Span;
|
||||
use std::{fmt::Display, mem::take};
|
||||
use std::{fmt::Display, iter, mem::take};
|
||||
|
||||
mod attr;
|
||||
pub use attr::{Attr, AttrList, AttrParts, SimpleAttr};
|
||||
|
@ -1099,27 +1099,45 @@ pub fn parse_attrs<'a>(
|
|||
/// To parse an entire stream as a tree,
|
||||
/// see [`parser_from`].
|
||||
///
|
||||
/// This parser does not take ownership over the iterator,
|
||||
/// allowing parsing to continue on the underlying token stream after
|
||||
/// attribute parsing has completed.
|
||||
/// Once attribute parsing is finished,
|
||||
/// parsing is able to continue on the underlying token stream as if the
|
||||
/// attributes were never present in XIR at all;
|
||||
/// this also allows this parser to be used as an attribute filter while
|
||||
/// ensuring that the attributes are syntactically valid.
|
||||
///
|
||||
/// For more information on contexts,
|
||||
/// and the parser in general,
|
||||
/// see the [module-level documentation](self).
|
||||
pub fn attr_parser_from(
|
||||
toks: impl TokenStream,
|
||||
) -> impl Iterator<Item = Result<Attr>> {
|
||||
toks.scan(ParserState::with(Stack::IsolatedAttrEmpty), parse)
|
||||
.filter_map(|parsed| match parsed {
|
||||
Ok(Parsed::Attr(attr)) => Some(Ok(attr)),
|
||||
Ok(Parsed::Incomplete) => None,
|
||||
Err(err) => Some(Err(err)),
|
||||
#[inline]
|
||||
pub fn attr_parser_from<'a>(
|
||||
toks: &'a mut impl TokenStream,
|
||||
) -> impl Iterator<Item = Result<Attr>> + 'a {
|
||||
let mut state = ParserState::with(Stack::IsolatedAttrEmpty);
|
||||
|
||||
// AttrEnd must have been encountered.
|
||||
Ok(Parsed::Done) => None,
|
||||
iter::from_fn(move || {
|
||||
loop {
|
||||
match toks.next().and_then(|tok| parse(&mut state, tok)) {
|
||||
None => return None,
|
||||
Some(Err(err)) => return Some(Err(err)),
|
||||
Some(Ok(Parsed::Attr(attr))) => return Some(Ok(attr)),
|
||||
Some(Ok(Parsed::Incomplete)) => continue,
|
||||
|
||||
// These make no sense in this context and should never occur.
|
||||
Ok(x @ (Parsed::Tree(_) | Parsed::AttrList(_))) => unreachable!(
|
||||
"unexpected yield by XIRT (Attr expected): {:?}",
|
||||
x
|
||||
),
|
||||
})
|
||||
// AttrEnd must have been encountered.
|
||||
Some(Ok(Parsed::Done)) => return None,
|
||||
|
||||
// These make no sense in this context and should never occur.
|
||||
Some(Ok(x @ (Parsed::Tree(_) | Parsed::AttrList(_)))) => {
|
||||
unreachable!(
|
||||
"unexpected yield by XIRT (Attr expected): {:?}",
|
||||
x
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -462,9 +462,9 @@ fn parse_attrs_isolated() {
|
|||
#[test]
|
||||
fn attr_parser_with_non_attr_token() {
|
||||
let name = "unexpected".unwrap_into();
|
||||
let toks = [Token::Open(name, *S)].into_iter();
|
||||
let mut toks = [Token::Open(name, *S)].into_iter();
|
||||
|
||||
let mut sut = attr_parser_from(toks);
|
||||
let mut sut = attr_parser_from(&mut toks);
|
||||
|
||||
assert_eq!(
|
||||
sut.next(),
|
||||
|
@ -479,7 +479,7 @@ fn parser_attr_multiple() {
|
|||
let val1 = AttrValue::Escaped("val1".into());
|
||||
let val2 = AttrValue::Escaped("val2".into());
|
||||
|
||||
let toks = [
|
||||
let mut toks = [
|
||||
Token::AttrName(attr1, *S),
|
||||
Token::AttrValue(val1, *S2),
|
||||
Token::AttrName(attr2, *S2),
|
||||
|
@ -488,7 +488,7 @@ fn parser_attr_multiple() {
|
|||
]
|
||||
.into_iter();
|
||||
|
||||
let mut sut = attr_parser_from(toks);
|
||||
let mut sut = attr_parser_from(&mut toks);
|
||||
|
||||
assert_eq!(sut.next(), Some(Ok(Attr::new(attr1, val1, (*S, *S2)))));
|
||||
assert_eq!(sut.next(), Some(Ok(Attr::new(attr2, val2, (*S2, *S3)))));
|
||||
|
|
Loading…
Reference in New Issue