tamer: tamec: POC lowering pipeline with XirfAutoClose and XirfToXir
This replaces the stub `derive_xmli` with the same result (well, minus a space before the '/' in the output) using what will become the lowering pipeline. Once again, this is quite verbose, and the lowering pipeline in general needs to be further abstracted away. Unlike the rest of the pipeline, an error during the derivation process will immediately terminate with an unrecoverable error, because we do not want to write partial files. This does not remove the garbage file, because the build system ought to do that itself (e.g. `make`)...but that is certainly open for debate. DEV-13708main
parent
29178f2360
commit
33d2b4f0b8
|
@ -30,6 +30,7 @@ extern crate tamer;
|
|||
|
||||
use getopts::{Fail, Options};
|
||||
use std::{
|
||||
convert::Infallible,
|
||||
env,
|
||||
error::Error,
|
||||
fmt::{self, Display, Write},
|
||||
|
@ -50,7 +51,8 @@ use tamer::{
|
|||
XirfToNirError,
|
||||
},
|
||||
parse::{
|
||||
lowerable, FinalizeError, Lower, ParseError, ParsedObject, UnknownToken,
|
||||
lowerable, FinalizeError, Lower, ParseError, ParsedObject, Token,
|
||||
UnknownToken,
|
||||
},
|
||||
xir::{
|
||||
self,
|
||||
|
@ -186,7 +188,7 @@ fn compile<R: Reporter>(
|
|||
false => {
|
||||
#[cfg(feature = "wip-asg-derived-xmli")]
|
||||
{
|
||||
derive_xmli(asg, fout)
|
||||
derive_xmli(asg, fout, &escaper)
|
||||
}
|
||||
#[cfg(not(feature = "wip-asg-derived-xmli"))]
|
||||
{
|
||||
|
@ -215,8 +217,51 @@ fn compile<R: Reporter>(
|
|||
fn derive_xmli(
|
||||
_asg: tamer::asg::Asg,
|
||||
mut fout: impl std::io::Write,
|
||||
escaper: &DefaultEscaper,
|
||||
) -> Result<(), UnrecoverableError> {
|
||||
fout.write_all(b"<it-has-begun />")?;
|
||||
use tamer::{
|
||||
convert::ExpectInto,
|
||||
iter::TrippableIterator,
|
||||
parse::terminal,
|
||||
span::UNKNOWN_SPAN,
|
||||
xir::{
|
||||
autoclose::XirfAutoClose,
|
||||
flat::{Depth, Text, XirfToXir},
|
||||
writer::XmlWriter,
|
||||
OpenSpan,
|
||||
},
|
||||
};
|
||||
|
||||
// Note how this does not contain a closing token;
|
||||
// it is closed by `XirfAutoClose`.
|
||||
let xir_toks = vec![XirfToken::Open(
|
||||
"it-has-begun".unwrap_into(),
|
||||
OpenSpan::without_name_span(UNKNOWN_SPAN),
|
||||
Depth(0),
|
||||
)];
|
||||
|
||||
let mut head = lowerable(xir_toks.into_iter().map(Ok));
|
||||
|
||||
// THIS IS A PROOF-OF-CONCEPT LOWERING PIPELINE.
|
||||
Lower::<
|
||||
ParsedObject<XirfToken<Text>, XirfToken<Text>, Infallible>,
|
||||
XirfAutoClose,
|
||||
_,
|
||||
>::lower::<_, UnrecoverableError>(&mut head, |xirf| {
|
||||
Lower::<XirfAutoClose, XirfToXir<Text>, _>::lower(xirf, |xir| {
|
||||
terminal::<XirfToXir<Text>, UnrecoverableError>(xir).while_ok(
|
||||
|toks| {
|
||||
// Write failures should immediately bail out;
|
||||
// we can't skip writing portions of the file and
|
||||
// just keep going!
|
||||
toks.write(&mut fout, Default::default(), escaper)?;
|
||||
Ok::<_, UnrecoverableError>(())
|
||||
},
|
||||
// TODO: Remove bad file?
|
||||
// Let make do it?
|
||||
)
|
||||
})
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -391,6 +436,20 @@ impl From<FinalizeError> for UnrecoverableError {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Infallible> for UnrecoverableError {
|
||||
fn from(_: Infallible) -> Self {
|
||||
unreachable!("<UnrecoverableError as From<Infallible>>::from")
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Token> From<ParseError<T, Infallible>> for UnrecoverableError {
|
||||
fn from(_: ParseError<T, Infallible>) -> Self {
|
||||
unreachable!(
|
||||
"<UnrecoverableError as From<ParseError<T, Infallible>>>::from"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseError<UnknownToken, xir::Error>> for RecoverableError {
|
||||
fn from(e: ParseError<UnknownToken, xir::Error>) -> Self {
|
||||
Self::XirParseError(e)
|
||||
|
|
|
@ -30,7 +30,7 @@ mod trace;
|
|||
pub mod util;
|
||||
|
||||
pub use error::{FinalizeError, ParseError};
|
||||
pub use lower::{lowerable, Lower, LowerIter, ParsedObject};
|
||||
pub use lower::{lowerable, terminal, Lower, LowerIter, ParsedObject};
|
||||
pub use parser::{FinalizedParser, Parsed, ParsedResult, Parser};
|
||||
pub use state::{
|
||||
context::{Context, Empty as EmptyContext, NoContext},
|
||||
|
|
|
@ -257,6 +257,8 @@ pub type WidenedParsedResult<S, E> =
|
|||
/// itself a [`ParseState`].
|
||||
///
|
||||
/// See [`ParsedObject`] for more information.
|
||||
///
|
||||
/// This is the dual of [`terminal`].
|
||||
pub fn lowerable<T: Token, O: Object, E: Diagnostic + PartialEq>(
|
||||
iter: impl Iterator<Item = Result<O, E>>,
|
||||
) -> impl Iterator<Item = ParsedResult<ParsedObject<T, O, E>>> {
|
||||
|
@ -265,6 +267,28 @@ pub fn lowerable<T: Token, O: Object, E: Diagnostic + PartialEq>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Indicate a terminal parser in a lowering pipeline,
|
||||
/// and unwrap the parse API.
|
||||
///
|
||||
/// This is the dual of [`lowerable`],
|
||||
/// responsible for breaking out of the pipeline for processing of the
|
||||
/// final object stream.
|
||||
///
|
||||
/// [`Parsed::Incomplete`] is filtered.
|
||||
/// Errors are lifted into `E` just as would be expected by [`Lower`].
|
||||
pub fn terminal<
|
||||
S: ParseState,
|
||||
E: Diagnostic + From<ParseError<S::Token, S::Error>>,
|
||||
>(
|
||||
iter: impl Iterator<Item = ParsedResult<S>>,
|
||||
) -> impl Iterator<Item = Result<S::Object, E>> {
|
||||
iter.filter_map(|result| match result {
|
||||
Ok(Parsed::Incomplete) => None,
|
||||
Ok(Parsed::Object(obj)) => Some(Ok(obj)),
|
||||
Err(e) => Some(Err(e.into())),
|
||||
})
|
||||
}
|
||||
|
||||
/// Representation of a [`ParseState`] producing some type of [`Object`].
|
||||
///
|
||||
/// This is intended to be used not as a value,
|
||||
|
|
|
@ -115,7 +115,7 @@ use XirfAutoClose::*;
|
|||
///
|
||||
/// See the [module-level documentation](super) for more information.
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
enum XirfAutoClose {
|
||||
pub enum XirfAutoClose {
|
||||
/// Element contains no children and can be self-closing.
|
||||
#[default]
|
||||
EmptyEle,
|
||||
|
@ -250,7 +250,7 @@ impl From<PDepth> for Depth {
|
|||
|
||||
/// Stack of open elements and associated metadata.
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct AutoCloseStack(Vec<StackItem>);
|
||||
pub struct AutoCloseStack(Vec<StackItem>);
|
||||
|
||||
type StackItem = (QName, Span, VDepth, PDepth);
|
||||
|
||||
|
|
Loading…
Reference in New Issue