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-7145main
parent
7b9bc9e108
commit
88fa0688fa
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue