-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
1,523 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use core::{any::TypeId, marker::PhantomData, ops::Range}; | ||
|
||
use crate::core::{EventFlow, PluginResult, StrRange}; | ||
|
||
pub trait Block: Sized + 'static { | ||
#[inline] | ||
fn begin_prompt() -> &'static str { | ||
"{" | ||
} | ||
|
||
#[inline] | ||
fn end_prompt() -> &'static str { | ||
"}" | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct Plugin<T: Block>(Option<Range<usize>>, PhantomData<T>); | ||
|
||
impl<T: Block> Default for Plugin<T> { | ||
fn default() -> Self { | ||
Self(None, PhantomData) | ||
} | ||
} | ||
|
||
impl<T: Block> Plugin<T> { | ||
pub fn last(&self) -> Option<Range<usize>> { | ||
self.0.clone() | ||
} | ||
} | ||
|
||
impl<T: Block> crate::core::Plugin for Plugin<T> { | ||
fn take_signal<P: crate::core::Plugin>( | ||
signal: StrRange, | ||
mut flow: EventFlow<P>, | ||
) -> PluginResult<Option<TypeId>> { | ||
if signal.substr() == T::begin_prompt() { | ||
let (simple_flow, plugins) = flow.swap_plugins(&mut ()); | ||
// TODO: skip counted | ||
Ok(Some(TypeId::of::<Self>())) | ||
} else { | ||
Ok(None) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
[package] | ||
name = "rewrite1" | ||
version.workspace = true | ||
authors.workspace = true | ||
license.workspace = true | ||
edition.workspace = true | ||
repository.workspace = true | ||
|
||
[features] | ||
std = ["indextree/std", "rand?/std"] | ||
lang = ["eval", "petgraph", "rand", "bitflags", "thiserror"] | ||
serde = ["dep:serde", "petgraph?/serde-1", "rand?/serde"] | ||
|
||
[dependencies] | ||
indextree = { version = "4.6.0", default-features = false } | ||
eval = { version = "0.4.3", default-features = false, optional = true } | ||
petgraph = { version = "0.6.4", default-features = false, optional = true } | ||
rand = { version = "0.8.5", default-features = false, optional = true, features = [ | ||
"std_rng", | ||
] } | ||
bitflags = { version = "2.4.2", default-features = false, optional = true } | ||
thiserror = { version = "1.0.58", default-features = false, optional = true } | ||
serde = { version = "1.0.197", default-features = false, optional = true, features = [ | ||
"derive", | ||
] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
pub mod find; | ||
|
||
mod chain; | ||
mod terminate; | ||
|
||
pub use self::{ | ||
chain::{Chain, ChainOf}, | ||
terminate::{Terminate, TerminateOf}, | ||
}; | ||
|
||
use self::find::Find; | ||
use crate::{utils, Event, Parser, Plugin}; | ||
use indextree::{Arena, NodeId}; | ||
|
||
#[derive(Copy, Clone, Debug, Default)] | ||
pub struct AndThen<T, U>(pub T, pub U); | ||
|
||
impl<T: Plugin, U: Plugin> Plugin for AndThen<T, U> { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
T::take(state, tree).and_then(|taken1| { | ||
let maybe_taken2 = U::take(state, tree); | ||
match maybe_taken2 { | ||
Some(taken2) => { | ||
let taken1_start = utils::unwrap_event::<T>(&tree, taken1).start; | ||
let taken2_end = utils::unwrap_event::<U>(&tree, taken2).end; | ||
let parent = tree.new_node(Event::new::<Self>(taken1_start..taken2_end)); | ||
parent.append(taken1, tree); | ||
parent.append(taken2, tree); | ||
Some(parent) | ||
} | ||
None => { | ||
taken1.remove_subtree(tree); | ||
None | ||
} | ||
} | ||
}) | ||
} | ||
|
||
fn inner<P: Plugin>(&self) -> Option<&P> { | ||
utils::same_plugin(self) | ||
.or_else(|| self.0.inner()) | ||
.or_else(|| self.1.inner()) | ||
} | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, Default)] | ||
pub struct OrElse<T, U>(pub T, pub U); | ||
|
||
impl<T: Plugin, U: Plugin> Plugin for OrElse<T, U> { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
T::take(state, tree).or_else(|| U::take(state, tree)) | ||
} | ||
|
||
fn inner<P: Plugin>(&self) -> Option<&P> { | ||
utils::same_plugin(self) | ||
.or_else(|| self.0.inner()) | ||
.or_else(|| self.1.inner()) | ||
} | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, Default)] | ||
pub struct Skip<T>(pub T); | ||
|
||
impl<T: Plugin> Plugin for Skip<T> { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
T::take(state, tree).map(|id| { | ||
let range = utils::unwrap_event::<T>(&tree, id).range(); | ||
id.remove(tree); | ||
tree.new_node(Event::new::<Self>(range)) | ||
}) | ||
} | ||
|
||
fn inner<P: Plugin>(&self) -> Option<&P> { | ||
utils::same_plugin(self).or_else(|| self.0.inner()) | ||
} | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, Default)] | ||
pub struct Raw<F: Find>(pub F); | ||
|
||
impl<F: Find> Plugin for Raw<F> { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
let self_ = state.plugin().inner::<Self>()?; | ||
let mut snap = state.snapshot(); | ||
let text_range = self_.0.find(&state.text()[snap.offset()..])?; | ||
let offset_text_range = snap.offset() + text_range.start..snap.offset() + text_range.end; | ||
snap.set_offset(offset_text_range.end); | ||
state.restore(snap); | ||
Some(tree.new_node(Event::new::<Self>(offset_text_range))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
use core::marker::PhantomData; | ||
|
||
use crate::{utils, Event, Plugin, Parser}; | ||
use indextree::{Arena, NodeId}; | ||
|
||
#[derive(Copy, Clone, Debug)] | ||
pub enum Chain { | ||
Exact(usize), | ||
Max(usize), | ||
Min(usize), | ||
Within { min: usize, max: usize }, | ||
} | ||
|
||
impl Plugin for Chain { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
let self_ = *state.plugin().inner::<Self>()?; | ||
let mut chain_builder = Builder::<S, S>::init(state, tree); | ||
match self_ { | ||
Chain::Exact(n) => chain_builder.take_exact(n), | ||
Chain::Max(n) => chain_builder.take_max(n), | ||
Chain::Min(n) => chain_builder.take_min(n), | ||
Chain::Within { min, max } => chain_builder.take_within(min, max), | ||
} | ||
.finish() | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct ChainOf<B: Plugin> { | ||
pub chain: Chain, | ||
phantom: PhantomData<B>, | ||
} | ||
|
||
impl<B: Plugin> Clone for ChainOf<B> { | ||
#[inline] | ||
fn clone(&self) -> Self { | ||
Self { | ||
chain: self.chain.clone(), | ||
phantom: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
impl<B: Plugin> Copy for ChainOf<B> {} | ||
|
||
impl<B: Plugin> ChainOf<B> { | ||
pub const fn new(chain: Chain) -> Self { | ||
Self { | ||
chain, | ||
phantom: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
impl<B: Plugin> Plugin for ChainOf<B> { | ||
fn take<S: Plugin>(state: &mut Parser<S>, tree: &mut Arena<Event>) -> Option<NodeId> { | ||
let self_ = *state.plugin().inner::<Self>()?; | ||
let mut chain_builder = Builder::<S, B>::init(state, tree); | ||
match self_.chain { | ||
Chain::Exact(n) => chain_builder.take_exact(n), | ||
Chain::Max(n) => chain_builder.take_max(n), | ||
Chain::Min(n) => chain_builder.take_min(n), | ||
Chain::Within { min, max } => chain_builder.take_within(min, max), | ||
} | ||
.finish() | ||
} | ||
} | ||
|
||
struct Builder<'s, 'a, S: Plugin, B: Plugin> { | ||
state: &'s mut Parser<'a, S>, | ||
tree: &'s mut Arena<Event>, | ||
parent_start: Option<usize>, | ||
parent_end: usize, | ||
parent_id: NodeId, | ||
phantom: PhantomData<B>, | ||
} | ||
|
||
impl<'s, 'a, S: Plugin, B: Plugin> Builder<'s, 'a, S, B> { | ||
fn init(state: &'s mut Parser<'a, S>, tree: &'s mut Arena<Event>) -> Self { | ||
let parent_id = tree.new_node(Event::new::<Chain>(0..0)); | ||
Self { | ||
state, | ||
tree, | ||
parent_start: None, | ||
parent_end: 0, | ||
parent_id, | ||
phantom: PhantomData, | ||
} | ||
} | ||
|
||
fn take_exact(&mut self, n: usize) -> &mut Self { | ||
for _ in 0..n { | ||
if self.state.exhausted() { | ||
self.parent_id.remove_subtree(self.tree); | ||
break; | ||
} | ||
match self | ||
.state | ||
.next_events(self.tree) | ||
.by_plugin::<B>() | ||
.take_one() | ||
{ | ||
Some(child_id) => { | ||
let child = *utils::unwrap_event::<B>(&self.tree, child_id); | ||
self.parent_id.append(child_id, self.tree); | ||
if self.parent_start.is_none() { | ||
self.parent_start = Some(child.start); | ||
} | ||
self.parent_end = child.end; | ||
} | ||
None => { | ||
self.parent_id.remove_subtree(self.tree); | ||
} | ||
} | ||
} | ||
self | ||
} | ||
|
||
fn take_max(&mut self, n: usize) -> &mut Self { | ||
if self.parent_id.is_removed(self.tree) { | ||
return self; | ||
} | ||
for _ in 0..n { | ||
if self.state.exhausted() { | ||
return self; | ||
} | ||
match self | ||
.state | ||
.next_events(self.tree) | ||
.by_plugin::<B>() | ||
.take_one() | ||
{ | ||
Some(child_id) => { | ||
let child = *utils::unwrap_event::<B>(&self.tree, child_id); | ||
self.parent_id.append(child_id, self.tree); | ||
if self.parent_start.is_none() { | ||
self.parent_start = Some(child.start); | ||
} | ||
self.parent_end = child.end; | ||
} | ||
None => break, | ||
} | ||
} | ||
self | ||
} | ||
|
||
fn take_within(&mut self, min: usize, max: usize) -> &mut Self { | ||
self.take_exact(min).take_max(max) | ||
} | ||
|
||
fn take_min(&mut self, n: usize) -> &mut Self { | ||
self.take_within(n, usize::MAX) | ||
} | ||
|
||
fn finish(&mut self) -> Option<NodeId> { | ||
let Some(parent) = self.tree.get_mut(self.parent_id) else { | ||
return None; | ||
}; | ||
parent.get_mut().start = self.parent_start.unwrap_or_default(); | ||
parent.get_mut().end = self.parent_end; | ||
Some(self.parent_id) | ||
} | ||
} |
Oops, something went wrong.