use std::fmt; use std::rc::Rc; use orchid_base::error::OrcRes; use orchid_base::name::Sym; use orchid_extension::context::i; use super::any_match::any_match; use super::build::mk_any; use super::shared::AnyMatcher; use super::state::{MatchState, StateEntry}; use super::vec_attrs::vec_attrs; use crate::macros::mactree::{MacTreeSeq, Ph, PhKind}; use crate::macros::{MacTok, MacTree}; pub struct Matcher { inner: AnyMatcher, } impl Matcher { pub async fn new(pattern: MacTreeSeq) -> OrcRes { let mut pattern = Rc::unwrap_or_clone(pattern.items); let kind = PhKind::Vector { at_least_one: false, priority: 0 }; let first = pattern.first().expect("Empty pattern is not allowed"); if vec_attrs(first).is_none() { let pos = first.pos(); pattern.insert(0, MacTok::Ph(Ph { name: i().i("::before").await, kind }).at(pos)); } let last = pattern.last().expect("first returned Some above"); if vec_attrs(last).is_none() { let pos = last.pos(); pattern.insert(0, MacTok::Ph(Ph { name: i().i("::after").await, kind }).at(pos)); } Ok(Matcher { inner: mk_any(&pattern).await? }) } /// Also returns the head and tail, which should be matched by overarching /// matchers attempted later. pub async fn apply<'a>( &self, seq: &'a [MacTree], save_loc: &dyn Fn(Sym) -> bool, ) -> Option<(&'a [MacTree], MatchState<'a>, &'a [MacTree])> { let mut result = any_match(&self.inner, seq, &save_loc)?; async fn remove_frame<'a>(result: &mut MatchState<'a>, key: &str) -> &'a [MacTree] { match result.remove(i().i(key).await) { Some(StateEntry::Scalar(_)) => panic!("{key} is defined in the constructor as a Vec"), Some(StateEntry::Vec(v)) => v, None => &[], } } let before = remove_frame(&mut result, "::before").await; let after = remove_frame(&mut result, "::after").await; Some((before, result, after)) } } impl fmt::Display for Matcher { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } impl fmt::Debug for Matcher { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NamedMatcher({self})") } }