tamer: parse (Transitionable): New

This simply removes boilerplate.

This will receive concrete examples once I come up with docs for the entire
module; there's boilerplate involved in testing and documenting this in
isolation and the time investment is not worth it yet until I'm certain that
this will not be changed.

DEV-10863
main
Mike Gerwitz 2022-03-30 10:00:17 -04:00
parent 1e278cbe26
commit 5c16add95d
2 changed files with 41 additions and 7 deletions

View File

@ -20,7 +20,7 @@
use super::{SymAttrs, XmloError};
use crate::{
obj::xmlo::{Dim, SymDtype, SymType},
parse::{self, ParseState, ParseStatus, Transition, TransitionResult},
parse::{self, ParseState, Transition, TransitionResult, Transitionable},
span::Span,
sym::{st::*, SymbolId},
xir::{attr::Attr, flat::Object as Xirf, QName},
@ -240,12 +240,8 @@ impl ParseState for SymtableState {
(
Sym(_tspan, name, mut attrs),
Xirf::Attr(Attr(key, value, (_, span))),
) => {
let result = Self::parse_sym_attr(&mut attrs, key, value, span)
.map(|_: ()| ParseStatus::Incomplete);
Transition(Sym(span, name, attrs)).result(result)
}
) => Self::parse_sym_attr(&mut attrs, key, value, span)
.transition(Sym(span, name, attrs)),
todo => todo!("{todo:?}"),
}

View File

@ -364,6 +364,44 @@ impl<S: ParseState> FromResidual<Result<Infallible, TransitionResult<S>>>
}
}
/// An object able to be used as data for a state [`Transition`].
///
/// This flips the usual order of things:
/// rather than using a method of [`Transition`] to provide data,
/// this starts with the data and produces a transition from it.
/// This is sometimes necessary to satisfy ownership/borrowing rules.
///
/// This trait simply removes boilerplate associated with storing
/// intermediate values and translating into the resulting type.
pub trait Transitionable<S: ParseState> {
/// Perform a state transition to `S` using [`Self`] as the associated
/// data.
///
/// This may be necessary to satisfy ownership/borrowing rules when
/// state data from `S` is used to compute [`Self`].
fn transition(self, to: S) -> TransitionResult<S>;
}
impl<S, E> Transitionable<S> for Result<ParseStatus<S>, E>
where
S: ParseState,
<S as ParseState>::Error: From<E>,
{
fn transition(self, to: S) -> TransitionResult<S> {
Transition(to).result(self)
}
}
impl<S, E> Transitionable<S> for Result<(), E>
where
S: ParseState,
<S as ParseState>::Error: From<E>,
{
fn transition(self, to: S) -> TransitionResult<S> {
Transition(to).result(self.map(|_| ParseStatus::Incomplete))
}
}
/// A streaming parser defined by a [`ParseState`] with exclusive
/// mutable access to an underlying [`TokenStream`].
///