tamer: parse: Move parse::lower into Lower
This also modifies `poc` such that `Lower` is invoked as an associated function rather than a method to emphasize the pattern that is forming, so that it can be later abstracted away. DEV-11864main
parent
f40f8bbafc
commit
63aa452197
|
@ -191,15 +191,17 @@ fn load_xmlo<'a, P: AsRef<Path>, S: Escaper>(
|
|||
let (mut asg, mut state) = into_iter_while_ok::<_, _, _, TameldError, _>(
|
||||
XmlXirReader::new(file, escaper, ctx),
|
||||
|toks| {
|
||||
flat::State::<64>::parse(toks).lower::<XmloReader, _, _>(
|
||||
Lower::<flat::State<64>, XmloReader>::lower(
|
||||
&mut flat::State::<64>::parse(toks),
|
||||
|xmlo| {
|
||||
let mut iter = xmlo.scan(false, |st, rtok| {
|
||||
match st {
|
||||
true => None,
|
||||
false => {
|
||||
*st = matches!(rtok, Ok(Parsed::Object(XmloToken::Eoh(..))));
|
||||
Some(rtok)
|
||||
},
|
||||
let mut iter = xmlo.scan(false, |st, rtok| match st {
|
||||
true => None,
|
||||
false => {
|
||||
*st = matches!(
|
||||
rtok,
|
||||
Ok(Parsed::Object(XmloToken::Eoh(..)))
|
||||
);
|
||||
Some(rtok)
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -684,65 +684,12 @@ impl<S: ParseState, I: TokenStream<S::Token>> Parser<S, I> {
|
|||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Lower the IR produced by this [`Parser`] into another IR by piping
|
||||
/// the output to a new parser defined by the [`ParseState`] `LS`.
|
||||
///
|
||||
/// This parser consumes tokens `S::Token` and produces the IR
|
||||
/// `S::Output`.
|
||||
/// If there is some other [`ParseState`] `LS` such that
|
||||
/// `LS::Token == S::Output`
|
||||
/// (that is—the output of this parser is the input to another),
|
||||
/// then this method will wire the two together into a new iterator
|
||||
/// that produces `LS::Output`.
|
||||
///
|
||||
/// Visually, we have,
|
||||
/// within the provided closure `f`,
|
||||
/// a [`LowerIter`] that acts as this pipeline:
|
||||
///
|
||||
/// ```text
|
||||
/// (S::Token) -> (S::Output == LS::Token) -> (LS::Output)
|
||||
/// ```
|
||||
///
|
||||
/// The new iterator is a [`LowerIter`],
|
||||
/// and scoped to the provided closure `f`.
|
||||
/// The outer [`Result`] of `Self`'s [`ParsedResult`] is stripped by
|
||||
/// a [`TripIter`] before being provided as input to a new push
|
||||
/// [`Parser`] utilizing `LS`.
|
||||
/// A push parser,
|
||||
/// rather than pulling tokens from a [`TokenStream`],
|
||||
/// has tokens pushed into it;
|
||||
/// this parser is created automatically for you.
|
||||
///
|
||||
/// _TODO_: There's no way to access the inner parser for error recovery
|
||||
/// after tripping the [`TripIter`].
|
||||
/// Consequently,
|
||||
/// this API (likely the return type) will change.
|
||||
#[inline]
|
||||
pub fn lower<LS, U, E>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut LowerIter<S, Parser<S, I>, LS>) -> Result<U, E>,
|
||||
) -> Result<U, E>
|
||||
where
|
||||
LS: ParseState<Token = S::Object>,
|
||||
<S as ParseState>::Object: Token,
|
||||
<LS as ParseState>::Context: Default,
|
||||
ParseError<S::Token, S::Error>: Into<E>,
|
||||
{
|
||||
self.while_ok(|toks| {
|
||||
// TODO: This parser is not accessible after error recovery!
|
||||
let lower = LS::parse(iter::empty());
|
||||
let mut iter = LowerIter { lower, toks };
|
||||
f(&mut iter)
|
||||
})
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// An IR lowering operation that pipes the output of one [`Parser`] to the
|
||||
/// input of another.
|
||||
///
|
||||
/// This is produced by [`Parser::lower`].
|
||||
/// This is produced by [`Lower`].
|
||||
pub struct LowerIter<'a, 'b, S, I, LS>
|
||||
where
|
||||
S: ParseState,
|
||||
|
@ -784,12 +731,66 @@ where
|
|||
LS: ParseState<Token = S::Object>,
|
||||
<S as ParseState>::Object: Token,
|
||||
{
|
||||
/// Lower the IR produced by this [`Parser`] into another IR by piping
|
||||
/// the output to a new parser defined by the [`ParseState`] `LS`.
|
||||
///
|
||||
/// This parser consumes tokens `S::Token` and produces the IR
|
||||
/// `S::Output`.
|
||||
/// If there is some other [`ParseState`] `LS` such that
|
||||
/// `LS::Token == S::Output`
|
||||
/// (that is—the output of this parser is the input to another),
|
||||
/// then this method will wire the two together into a new iterator
|
||||
/// that produces `LS::Output`.
|
||||
///
|
||||
/// Visually, we have,
|
||||
/// within the provided closure `f`,
|
||||
/// a [`LowerIter`] that acts as this pipeline:
|
||||
///
|
||||
/// ```text
|
||||
/// (S::Token) -> (S::Output == LS::Token) -> (LS::Output)
|
||||
/// ```
|
||||
///
|
||||
/// The new iterator is a [`LowerIter`],
|
||||
/// and scoped to the provided closure `f`.
|
||||
/// The outer [`Result`] of `Self`'s [`ParsedResult`] is stripped by
|
||||
/// a [`TripIter`] before being provided as input to a new push
|
||||
/// [`Parser`] utilizing `LS`.
|
||||
/// A push parser,
|
||||
/// rather than pulling tokens from a [`TokenStream`],
|
||||
/// has tokens pushed into it;
|
||||
/// this parser is created automatically for you.
|
||||
///
|
||||
/// _TODO_: There's no way to access the inner parser for error recovery
|
||||
/// after tripping the [`TripIter`].
|
||||
/// Consequently,
|
||||
/// this API (likely the return type) will change.
|
||||
#[inline]
|
||||
fn lower<U, E>(
|
||||
&mut self,
|
||||
f: impl FnOnce(&mut LowerIter<S, Self, LS>) -> Result<U, E>,
|
||||
) -> Result<U, E>
|
||||
where
|
||||
Self: Iterator<Item = ParsedResult<S>> + Sized,
|
||||
<LS as ParseState>::Context: Default,
|
||||
ParseError<S::Token, S::Error>: Into<E>,
|
||||
ParseError<LS::Token, LS::Error>: Into<E>,
|
||||
{
|
||||
self.while_ok(|toks| {
|
||||
// TODO: This parser is not accessible after error recovery!
|
||||
let lower = LS::parse(iter::empty());
|
||||
let mut iter = LowerIter { lower, toks };
|
||||
f(&mut iter)
|
||||
})
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Perform a lowering operation between two parsers where the context
|
||||
/// is both received and returned.
|
||||
///
|
||||
/// This allows state to be shared among parsers.
|
||||
///
|
||||
/// See [`ParseState::parse_with_context`] for more information.
|
||||
/// See [`Lower::lower`] and [`ParseState::parse_with_context`] for more
|
||||
/// information.
|
||||
fn lower_with_context<U, E>(
|
||||
&mut self,
|
||||
ctx: LS::Context,
|
||||
|
|
Loading…
Reference in New Issue