tamer: xir::parse::ele: Abstract node matching

This introduces `NodeMatcher`, with the intent of introducing wildcard QName
matches for e.g. `t:*` nodes.  It's not yet clear if I'll expand this to
support text nodes yet, or if I'll convert text nodes into elements to
re-use the existing system (which I had initially planned on doing, but
didn't because of the work and expense (token expansion) involved in the
conversion).

DEV-7145
main
Mike Gerwitz 2022-08-10 13:50:40 -04:00
parent 7b9bc9e108
commit 88fa0688fa
2 changed files with 42 additions and 7 deletions

View File

@ -26,4 +26,6 @@ mod attr;
mod ele;
pub use attr::{parse_attrs, AttrParseError, AttrParseState};
pub use ele::{EleParseCfg, EleParseState, StateStack, StateStackContext};
pub use ele::{
EleParseCfg, EleParseState, NodeMatcher, StateStack, StateStackContext,
};

View File

@ -20,6 +20,7 @@
//! Element parser generator for parsing of [XIRF](super::super::flat).
use arrayvec::ArrayVec;
use std::fmt::Display;
use crate::{
diagnose::{panic::DiagnosticPanic, Annotate},
@ -29,6 +30,7 @@ use crate::{
ClosedParseState, Context, ParseState, Token, Transition,
TransitionResult,
},
xir::QName,
};
#[cfg(doc)]
@ -194,6 +196,37 @@ impl<S: ClosedParseState> StateStack<S> {
}
}
/// Match some type of node.
#[derive(Debug, PartialEq, Eq)]
pub enum NodeMatcher {
/// Static [`QName`] with a simple equality check.
QName(QName),
}
impl NodeMatcher {
/// Match against the provided [`QName`].
pub fn matches(&self, qname: QName) -> bool {
matches!(
self,
Self::QName(qn_match) if qn_match == &qname
)
}
}
impl From<QName> for NodeMatcher {
fn from(qname: QName) -> Self {
Self::QName(qname)
}
}
impl Display for NodeMatcher {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::QName(qname) => Display::fmt(qname, f),
}
}
}
#[macro_export]
macro_rules! ele_parse {
(
@ -486,8 +519,8 @@ macro_rules! ele_parse {
/// [`QName`](crate::xir::QName) of the element recognized
/// by this parser.
#[allow(dead_code)] // used by sum parser
const fn qname() -> crate::xir::QName {
$qname
fn matcher() -> crate::xir::parse::NodeMatcher {
crate::xir::parse::NodeMatcher::from($qname)
}
/// Yield the expected depth of child elements,
@ -687,7 +720,7 @@ macro_rules! ele_parse {
(
Expecting_(cfg),
XirfToken::Open(qname, span, depth)
) if qname == $qname => {
) if $nt::matcher().matches(qname) => {
Transition(Attrs_(
(cfg, span.tag_span(), depth),
parse_attrs(qname, span)
@ -881,7 +914,7 @@ macro_rules! ele_parse {
let ntrefs = [
$(
$ntref::qname(),
$ntref::matcher(),
)*
];
let expected = OpenEleSumList::wrap(&ntrefs);
@ -948,7 +981,7 @@ macro_rules! ele_parse {
let ntrefs = [
$(
$ntref::qname(),
$ntref::matcher(),
)*
];
let expected = OpenEleSumList::wrap(&ntrefs);
@ -1013,7 +1046,7 @@ macro_rules! ele_parse {
(
Expecting_(cfg),
XirfToken::Open(qname, span, depth)
) if qname == $ntref::qname() => {
) if $ntref::matcher().matches(qname) => {
ele_parse!(@!ntref_delegate
stack,
match cfg.repeat {