Public API and docs

This commit is contained in:
2023-05-26 15:23:15 +01:00
parent 3c1a6e2be2
commit fdf18e6ff8
99 changed files with 503 additions and 406 deletions

View File

@@ -0,0 +1,202 @@
use std::fmt::Write;
use std::rc::Rc;
use super::any_match::any_match;
use super::build::mk_any;
use crate::ast::Expr;
use crate::interner::{InternedDisplay, Interner, Sym, Tok};
use crate::representations::Primitive;
use crate::rule::matcher::Matcher;
use crate::rule::state::State;
use crate::utils::{sym2string, unwrap_or, Side};
pub enum ScalMatcher {
P(Primitive),
Name(Sym),
S(char, Box<AnyMatcher>),
Lambda(Box<ScalMatcher>, Box<AnyMatcher>),
Placeh(Tok<String>),
}
pub enum VecMatcher {
Placeh {
key: Tok<String>,
nonzero: bool,
},
Scan {
left: Box<VecMatcher>,
sep: Vec<ScalMatcher>,
right: Box<VecMatcher>,
/// The separator traverses the sequence towards this side
direction: Side,
},
Middle {
/// Matches the left outer region
left: Box<VecMatcher>,
/// Matches the left separator
left_sep: Vec<ScalMatcher>,
/// Matches the middle - can only ever be a plain placeholder
mid: Box<VecMatcher>,
/// Matches the right separator
right_sep: Vec<ScalMatcher>,
/// Matches the right outer region
right: Box<VecMatcher>,
/// Order of significance for sorting equally good solutions based on
/// the length of matches on either side.
///
/// Vectorial keys that appear on either side, in priority order
key_order: Vec<Tok<String>>,
},
}
pub enum AnyMatcher {
Scalar(Vec<ScalMatcher>),
Vec { left: Vec<ScalMatcher>, mid: VecMatcher, right: Vec<ScalMatcher> },
}
impl Matcher for AnyMatcher {
fn new(pattern: Rc<Vec<Expr>>) -> Self {
mk_any(&pattern)
}
fn apply<'a>(&self, source: &'a [Expr]) -> Option<State<'a>> {
any_match(self, source)
}
}
// ################ InternedDisplay ################
fn disp_scalv(
scalv: &[ScalMatcher],
f: &mut std::fmt::Formatter<'_>,
i: &Interner,
) -> std::fmt::Result {
let (head, tail) = unwrap_or!(scalv.split_first(); return Ok(()));
head.fmt_i(f, i)?;
for s in tail.iter() {
write!(f, " ")?;
s.fmt_i(f, i)?;
}
Ok(())
}
impl InternedDisplay for ScalMatcher {
fn fmt_i(
&self,
f: &mut std::fmt::Formatter<'_>,
i: &Interner,
) -> std::fmt::Result {
match self {
Self::P(p) => write!(f, "{:?}", p),
Self::Placeh(n) => write!(f, "${}", i.r(*n)),
Self::Name(n) => write!(f, "{}", sym2string(*n, i)),
Self::S(c, body) => {
f.write_char(*c)?;
body.fmt_i(f, i)?;
f.write_char(match c {
'(' => ')',
'[' => ']',
'{' => '}',
_ => unreachable!(),
})
},
Self::Lambda(arg, body) => {
f.write_char('\\')?;
arg.fmt_i(f, i)?;
f.write_char('.')?;
body.fmt_i(f, i)
},
}
}
}
impl InternedDisplay for VecMatcher {
fn fmt_i(
&self,
f: &mut std::fmt::Formatter<'_>,
i: &Interner,
) -> std::fmt::Result {
match self {
Self::Placeh { key, nonzero } => {
if *nonzero {
f.write_char('.')?;
};
write!(f, "..${}", i.r(*key))
},
Self::Scan { left, sep, right, direction } => {
let arrow = match direction {
Side::Left => " <== ",
Side::Right => " ==> ",
};
write!(f, "Scan{{")?;
left.fmt_i(f, i)?;
f.write_str(arrow)?;
disp_scalv(sep, f, i)?;
f.write_str(arrow)?;
right.fmt_i(f, i)?;
write!(f, "}}")
},
Self::Middle { left, left_sep, mid, right_sep, right, .. } => {
write!(f, "Middle{{")?;
left.fmt_i(f, i)?;
f.write_str("|")?;
disp_scalv(left_sep, f, i)?;
f.write_str("|")?;
mid.fmt_i(f, i)?;
f.write_str("|")?;
disp_scalv(right_sep, f, i)?;
f.write_str("|")?;
right.fmt_i(f, i)?;
write!(f, "}}")
},
}
}
}
impl InternedDisplay for AnyMatcher {
fn fmt_i(
&self,
f: &mut std::fmt::Formatter<'_>,
i: &Interner,
) -> std::fmt::Result {
match self {
Self::Scalar(s) => {
write!(f, "(")?;
disp_scalv(s, f, i)?;
write!(f, ")")
},
Self::Vec { left, mid, right } => {
write!(f, "[")?;
disp_scalv(left, f, i)?;
write!(f, "|")?;
mid.fmt_i(f, i)?;
write!(f, "|")?;
disp_scalv(right, f, i)?;
write!(f, "]")
},
}
}
}
// ################ External ################
/// A [Matcher] implementation that builds a priority-order tree of the
/// vectorial placeholders and handles the scalars on leaves.
pub struct VectreeMatcher(AnyMatcher);
impl Matcher for VectreeMatcher {
fn new(pattern: Rc<Vec<Expr>>) -> Self {
Self(AnyMatcher::new(pattern))
}
fn apply<'a>(&self, source: &'a [Expr]) -> Option<State<'a>> {
self.0.apply(source)
}
}
impl InternedDisplay for VectreeMatcher {
fn fmt_i(
&self,
f: &mut std::fmt::Formatter<'_>,
i: &Interner,
) -> std::fmt::Result {
self.0.fmt_i(f, i)
}
}