tamer: parse::util::expand: Delete module

Oh, boy, I had forgotten about this, until I started working on some
SuperState stuff and discovered this again due to a compiler error.  Don't
want to fix something that isn't used.

But this does not bring back great memories.  It's unfortunate that it
didn't work out; I'm pretty sure this was part of ~1mo of wasted effort
going down a path that I ultimately had to abort.  Not good times.  I'm
still behind from it.

DEV-13708
main
Mike Gerwitz 2023-03-29 15:30:51 -04:00
parent 15fd2de437
commit 68e2d5d10e
4 changed files with 0 additions and 441 deletions

View File

@ -257,42 +257,6 @@ impl<S: ParseState> TransitionResult<S> {
Result(result, la) => falive(st, result, la, bctx),
}
}
/// Conditionally map to a [`TransitionResult`] based on whether the
/// inner [`TransitionData`] represents an object.
pub(in super::super) fn branch_obj_la<SB: ParseState>(
self,
fobj: impl FnOnce(
Transition<S>,
<S as ParseState>::Object,
Option<Lookahead<<S as ParseState>::Token>>,
) -> TransitionResult<<SB as ParseState>::Super>,
fother: impl FnOnce(Transition<S>) -> Transition<SB>,
) -> TransitionResult<<SB as ParseState>::Super>
where
S: PartiallyStitchableParseState<SB>,
{
use ParseStatus::{Incomplete, Object};
use TransitionData::{Dead, Result};
let Self(st, data) = self;
match data {
Result(Ok(Object(obj)), la) => fobj(st, obj, la).into_super(),
// Can't use `TransitionData::inner_into` since we only have a
// `PartiallyStitchableParseState`,
// and `into_inner` requires being able to convert the inner
// object that we handled above.
Result(Ok(Incomplete), la) => fother(st)
.incomplete()
.maybe_with_lookahead(la.map(Lookahead::inner_into)),
Result(Err(e), la) => fother(st)
.err(e)
.maybe_with_lookahead(la.map(Lookahead::inner_into)),
Dead(Lookahead(la)) => fother(st).dead(la.into()),
}
}
}
/// Token to use as a lookahead token in place of the next token from the

View File

@ -25,8 +25,6 @@
//! they provide wrappers around core functionality that make it easier
//! to use outside of the domain of the parsing system itself.
pub mod expand;
use super::{prelude::*, state::TransitionData};
use crate::{f::Functor, span::Span, sym::SymbolId};
use std::fmt::Display;

View File

@ -1,145 +0,0 @@
// TAMER parsing framework utilities for token expansion
//
// Copyright (C) 2014-2023 Ryan Specialty, LLC.
//
// This file is part of TAME.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//! Token expansion utilities.
//!
//! _Expansion_ refers to the production of many [`Object`]s that are
//! derived from a single [`Token`].
//! An [`ExpandableParseState`] is a [`ClosedParseState`] that,
//! provided a [`Token`],
//! produces an [`Expansion`] of zero or more [`Expansion::Expanded`]
//! [`Object`]s before terminating with a [`Expansion::DoneExpanding`]
//! [`Token`] intended to replace the originally provided [`Token`].
//!
//! An [`ExpandableParseState`] can be stitched with a parent parser using
//! [`StitchExpansion`],
//! giving the perception of expanding into that parent's token stream.
use super::super::{prelude::*, state::Lookahead};
use crate::{
diagnose::{panic::DiagnosticOptionPanic, Annotate},
parse::state::PartiallyStitchableParseState,
};
/// Represents an expansion operation on some source token of type `T`.
///
/// See variants and [`ExpandableParseState`] for more information.
#[derive(Debug, PartialEq, Eq)]
pub enum Expansion<T, O: Object> {
/// A token of type `O` has been derived from the source token and
/// should be merged into the target token stream.
Expanded(O),
/// Expansion is complete and the source token should be replaced with
/// the inner `T`.
///
/// Since the expectation is that the parser has completed parsing and
/// no longer requires the token provided to it,
/// the parser yielding this variant _must not_ yield a token of
/// lookahead,
/// otherwise the system assume that the parser has an
/// implementation defect (bug) and will be forced to panic rather
/// than discard it.
DoneExpanding(T),
}
impl<T: Token, O: Object> Object for Expansion<T, O> {}
/// A [`ClosedParseState`] that is able to serve as an expansion parser.
///
/// An expansion parser is a parser yielding [`Expansion`],
/// intended to be integrated into another token stream.
pub trait ExpandableParseState<O: Object> = ClosedParseState
where
O: Token + Eq,
Self: ParseState<Object = Expansion<<Self as ParseState>::Token, O>>;
/// An [`ExpandableParseState`] capable of expanding into the token stream
/// of a parent [`ParseState`] `SP`.
pub trait ExpandableInto<SP: ParseState> =
ExpandableParseState<<SP as ParseState>::Object>
where
Self: ExpandableParseState<<SP as ParseState>::Object>
+ PartiallyStitchableParseState<SP>;
/// [`ExpandableParseState`] state stitching.
///
/// See [`Self::stitch_expansion`] for more information.
pub trait StitchExpansion: ClosedParseState {
/// Stitch a [`ExpandableParseState`] that is
/// [`ExpandableInto<SP>`](ExpandableInto).
///
/// This combines the state machine of an [`ExpandableParseState`],
/// allowing that parser to expand into the token stream of [`Self`].
///
/// Panics
/// ======
/// This will panic with diagnostic information if a token of lookahead
/// is provided with a [`Expansion::DoneExpanding`] variant.
/// See that variant for more information.
fn stitch_expansion<SP: ParseState, C>(
self,
tok: <Self as ParseState>::Token,
mut ctx: C,
into: impl Fn(Transition<Self>) -> Transition<SP>,
done: impl FnOnce(
Transition<Self>,
<SP as ParseState>::Token,
) -> TransitionResult<SP>,
) -> TransitionResult<<SP as ParseState>::Super>
where
Self: ExpandableInto<SP>,
C: AsMut<<Self as ParseState>::Context>,
{
use Expansion::{DoneExpanding, Expanded};
self.parse_token(tok, ctx.as_mut()).branch_obj_la(
|st, obj, la| match (obj, la) {
(Expanded(obj), la) => into(st)
.ok(obj)
.maybe_with_lookahead(la.map(Lookahead::inner_into)),
(DoneExpanding(tok), la) => {
// Uphold parser lookahead invariant.
la.diagnostic_expect_none(
|Lookahead(la_tok)| {
vec![
la_tok.span().note(
"this token of lookahead would be lost",
),
tok.span().internal_error(
"unexpected token of lookahead while \
completing expansion of this token",
),
]
},
"cannot provide lookahead token with \
Expansion::DoneExpanding",
);
done(st, tok.into()).into_super()
}
},
&into,
)
}
}
#[cfg(test)]
pub mod test;

View File

@ -1,258 +0,0 @@
// Tests for TAMER parsing framework utilities
//
// Copyright (C) 2014-2023 Ryan Specialty, LLC.
//
// This file is part of TAME.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use super::super::SPair;
use super::*;
use crate::{
span::{dummy::*, Span},
sym::{st::raw, SymbolId},
};
use std::{
assert_matches::assert_matches, convert::Infallible, fmt::Display,
marker::PhantomData,
};
#[derive(Debug, PartialEq, Eq)]
pub struct StitchableExpansionState<S: ClosedParseState, O: Object> {
st: S,
_phantom: PhantomData<O>,
}
impl<S: ClosedParseState, O: Object> Default for StitchableExpansionState<S, O>
where
S: Default,
{
fn default() -> Self {
Self {
st: Default::default(),
_phantom: Default::default(),
}
}
}
impl<S: ClosedParseState, O: Object> ParseState
for StitchableExpansionState<S, O>
where
S: ExpandableParseState<O> + StitchExpansion,
<S as ParseState>::Context: AsMut<<S as ParseState>::Context>,
{
type Token = S::Token;
type Object = O;
type Error = S::Error;
type Context = S::Context;
#[inline]
fn parse_token(
self,
tok: Self::Token,
ctx: &mut Self::Context,
) -> TransitionResult<Self::Super> {
let Self { st, _phantom } = self;
st.stitch_expansion(
tok,
ctx,
Transition::fmap(|st| Self { st, _phantom }),
|Transition(st), tok| Transition(Self { st, _phantom }).dead(tok),
)
}
fn is_accepting(&self, ctx: &Self::Context) -> bool {
self.st.is_accepting(ctx)
}
}
impl<S: ClosedParseState, O: Object> Display
for StitchableExpansionState<S, O>
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self {
st: parser,
_phantom,
} => {
write!(f, "{parser}, with Expansion stripped")
}
}
}
}
#[derive(Debug, PartialEq, Eq)]
struct TestObject(SPair);
impl Token for TestObject {
fn ir_name() -> &'static str {
"TestObject"
}
fn span(&self) -> Span {
match self {
Self(SPair(_, span)) => *span,
}
}
}
impl Display for TestObject {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self(spair) => Display::fmt(spair, f),
}
}
}
impl Object for TestObject {}
/// Just some parser to wrap for our tests.
///
/// Eventually we'll be able to more easily create these on-demand without so
/// so much boilerplate,
/// but that hasn't evolved yet.
#[derive(Debug, PartialEq, Eq, Default)]
struct TestParseState;
impl ParseState for TestParseState {
type Token = SPair;
type Object = Expansion<Self::Token, TestObject>;
type Error = Infallible;
fn parse_token(
self,
tok: Self::Token,
_ctx: &mut Self::Context,
) -> TransitionResult<Self::Super> {
match tok {
tok @ SPair(sym @ (STOP | DEAD_SYM), span) => {
let st = Transition(self).ok(Expansion::DoneExpanding(tok));
st.maybe_with_lookahead(if sym == DEAD_SYM {
// It doesn't matter what this token is for our tests.
Some(Lookahead(SPair(sym, span)))
} else {
None
})
}
_ => Transition(self).ok(Expansion::Expanded(TestObject(tok))),
}
}
fn is_accepting(&self, _ctx: &Self::Context) -> bool {
true
}
}
impl Display for TestParseState {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "doing its thing") // well, it is
}
}
impl StitchExpansion for TestParseState {}
const STOP: SymbolId = raw::L_YIELD;
const DEAD_SYM: SymbolId = raw::L_WARNING;
type ExpansionSut = StitchableExpansionState<TestParseState, TestObject>;
#[test]
fn expansion_can_be_stripped_for_stitching() {
let syma = "foo".into();
let symb = "bar".into();
let toks = vec![SPair(syma, S1), SPair(symb, S2), SPair(STOP, S3)];
// The wraps the above TestParseState to strip Expansion.
let mut sut = ExpansionSut::parse(toks.into_iter());
// Our test parser echoes back the tokens wrapped in an "expanded"
// `TestObject` until we reach `STOP`.
// The first two are expanded,
// and our SUT strips the expansion.
assert_eq!(
sut.next(),
Some(Ok(Parsed::Object(TestObject(SPair(syma, S1))))),
);
assert_eq!(
sut.next(),
Some(Ok(Parsed::Object(TestObject(SPair(symb, S2))))),
);
// The final `Expansion::DoneExpanding` is converted into a dead state
// transition.
// That manifests here as an `UnexpectedToken` error because nothing
// handled it within our parser,
// but this is expected to stitched via delegation,
// which _would_ handle this case.
assert_matches!(
sut.next(),
Some(Err(ParseError::UnexpectedToken(dead_tok, _)))
if dead_tok == SPair(STOP, S3)
);
}
// We must not lose lookahead tokens;
// see SUT for more information.
#[should_panic]
#[test]
fn expansion_stripping_panics_if_lookahead() {
let toks = vec![SPair(DEAD_SYM, S1)];
// The above token will trigger the panic on the first call.
let _ = ExpansionSut::parse(toks.into_iter()).next();
}
// This test would fail at compile-time.
#[test]
fn expandable_into_is_stitchable_with_target() {
// This is utilized only for its types in the below assertions.
#[derive(Debug, PartialEq, Eq)]
struct TargetParseState;
impl ParseState for TargetParseState {
type Token = SPair;
type Object = TestObject;
type Error = Infallible;
fn parse_token(
self,
_tok: Self::Token,
_ctx: &mut Self::Context,
) -> TransitionResult<Self::Super> {
unimplemented!()
}
fn is_accepting(&self, _ctx: &Self::Context) -> bool {
unimplemented!()
}
}
impl Display for TargetParseState {
fn fmt(&self, _f: &mut std::fmt::Formatter) -> std::fmt::Result {
unimplemented!()
}
}
// The `ExpandableInto` trait alias is responsible for asserting that a
// given parser is an expansion parser that is able to be converted
// into a parser stitchable with the target.
//
// If this fails but the above assertion succeeds,
// then the compatibility is working but something is wrong with the
// definition of `ExpandableInto`.
assert_impl_all!(TestParseState: ExpandableInto<TargetParseState>);
}