tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
// XIR element parser generator
|
|
|
|
//
|
|
|
|
// Copyright (C) 2014-2022 Ryan Specialty Group, LLC.
|
|
|
|
//
|
|
|
|
// This file is part of TAME.
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
//! Element parser generator for parsing of [XIRF](super::super::flat).
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
macro_rules! ele_parse {
|
|
|
|
(type Object = $objty:ty; $($rest:tt)*) => {
|
|
|
|
ele_parse!(@!nonterm_decl <$objty> $($rest)*)
|
|
|
|
};
|
|
|
|
|
|
|
|
(@!nonterm_decl <$objty:ty> $nt:ident := $($rest:tt)*) => {
|
|
|
|
ele_parse!(@!nonterm_def <$objty> $nt $($rest)*);
|
|
|
|
};
|
|
|
|
|
2022-07-13 23:42:51 -04:00
|
|
|
(@!nonterm_def <$objty:ty>
|
|
|
|
$nt:ident $qname:ident $(($($ntp:tt)*))?
|
|
|
|
{ $($matches:tt)* } $($rest:tt)*
|
|
|
|
) => {
|
|
|
|
ele_parse!(@!ele_expand_body <$objty> $nt $qname ($($($ntp)*)?) $($matches)*);
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
|
|
|
|
ele_parse! {
|
|
|
|
type Object = $objty;
|
|
|
|
$($rest)*
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
(@!nonterm_def <$objty:ty> $nt:ident ($ntreffirst:ident $(| $ntref:ident)+), $($rest:tt)*) => {
|
|
|
|
ele_parse!(@!ele_dfn_sum $nt [$ntfirst $($nt)*]);
|
|
|
|
|
|
|
|
ele_parse! {
|
|
|
|
$($rest)*
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
(@!nonterm_decl <$objty:ty>) => {};
|
|
|
|
|
|
|
|
// Expand the provided data to a more verbose form that provides the
|
|
|
|
// context necessary for state transitions.
|
2022-07-13 23:42:51 -04:00
|
|
|
(@!ele_expand_body <$objty:ty> $nt:ident $qname:ident ($($ntp:tt)*)
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
@ { $($attrbody:tt)* } => $attrmap:expr,
|
2022-07-13 23:42:51 -04:00
|
|
|
$(/$(($close_span:ident))? => $closemap:expr,)?
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
|
|
|
|
// Nonterminal references are provided as a list.
|
|
|
|
$(
|
|
|
|
$ntref:ident,
|
|
|
|
)*
|
|
|
|
) => {
|
|
|
|
ele_parse! {
|
2022-07-13 23:42:51 -04:00
|
|
|
@!ele_dfn_body <$objty> $nt $qname ($($ntp)*)
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
@ { $($attrbody)* } => $attrmap,
|
2022-07-13 23:42:51 -04:00
|
|
|
/$($($close_span)?)? => ele_parse!(@!ele_close $($closemap)?),
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
|
|
|
|
<> {
|
|
|
|
$(
|
|
|
|
$ntref,
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate state transitions of the form `(S) -> (S')`.
|
|
|
|
-> {
|
|
|
|
@ ->
|
|
|
|
$(
|
|
|
|
($nt::$ntref),
|
|
|
|
($nt::$ntref) ->
|
|
|
|
)* ($nt::ExpectClose_),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-07-13 15:02:46 -04:00
|
|
|
// No explicit Close mapping defaults to doing nothing at all
|
|
|
|
// (so yield Incomplete).
|
|
|
|
(@!ele_close) => {
|
|
|
|
crate::parse::ParseStatus::Incomplete
|
|
|
|
};
|
|
|
|
|
|
|
|
(@!ele_close $close:expr) => {
|
|
|
|
crate::parse::ParseStatus::Object($close)
|
|
|
|
};
|
|
|
|
|
2022-07-13 23:42:51 -04:00
|
|
|
(@!ele_dfn_body <$objty:ty> $nt:ident $qname:ident ($($open_span:ident)?)
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
// Attribute definition special form.
|
|
|
|
@ {
|
|
|
|
// We must lightly parse attributes here so that we can retrieve
|
|
|
|
// the field identifiers that may be later used as bindings in
|
|
|
|
// `$attrmap`.
|
|
|
|
$(
|
|
|
|
$(#[$fattr:meta])*
|
|
|
|
$field:ident: ($fmatch:tt) => $fty:ty,
|
|
|
|
)*
|
|
|
|
} => $attrmap:expr,
|
|
|
|
|
2022-07-13 15:02:46 -04:00
|
|
|
// Close expression
|
|
|
|
// (defaulting to Incomplete via @!ele_expand_body).
|
2022-07-13 23:42:51 -04:00
|
|
|
/$($close_span:ident)? => $closemap:expr,
|
2022-07-13 15:02:46 -04:00
|
|
|
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
// Nonterminal references.
|
|
|
|
<> {
|
|
|
|
$(
|
|
|
|
$ntref:ident,
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
|
|
|
|
-> {
|
|
|
|
@ -> ($ntfirst:path),
|
|
|
|
$(
|
|
|
|
($ntprev:path) -> ($ntnext:path),
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
) => {
|
|
|
|
// TODO
|
|
|
|
paste::paste! {
|
|
|
|
crate::attr_parse! {
|
|
|
|
struct [<$nt AttrsState_>] -> [<$nt Attrs_>] {
|
|
|
|
$(
|
|
|
|
$(#[$fattr])*
|
|
|
|
$field: ($fmatch) => $fty,
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc=concat!("Parser for element [`", stringify!($qname), "`].")]
|
|
|
|
#[derive(Debug, PartialEq, Eq, Default)]
|
|
|
|
enum $nt {
|
|
|
|
#[doc=concat!(
|
|
|
|
"Expecting opening tag for element [`",
|
|
|
|
stringify!($qname),
|
|
|
|
"`]."
|
|
|
|
)]
|
|
|
|
#[default]
|
|
|
|
Expecting_,
|
|
|
|
/// Recovery state ignoring all remaining tokens for this
|
|
|
|
/// element.
|
|
|
|
RecoverEleIgnore_(crate::xir::QName, crate::xir::OpenSpan, Depth),
|
|
|
|
RecoverEleIgnoreClosed_(crate::xir::QName, crate::xir::CloseSpan),
|
|
|
|
/// Parsing element attributes.
|
|
|
|
Attrs_([<$nt AttrsState_>]),
|
|
|
|
$(
|
|
|
|
$ntref($ntref),
|
|
|
|
)*
|
|
|
|
ExpectClose_(()),
|
|
|
|
/// Closing tag found and parsing of the element is
|
|
|
|
/// complete.
|
|
|
|
Closed_(crate::span::Span),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Display for $nt {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
use crate::{
|
|
|
|
fmt::{DisplayWrapper, TtQuote},
|
|
|
|
xir::fmt::TtOpenXmlEle,
|
|
|
|
};
|
|
|
|
|
|
|
|
match self {
|
|
|
|
Self::Expecting_ => write!(
|
|
|
|
f,
|
|
|
|
"expecting opening tag {}",
|
|
|
|
TtOpenXmlEle::wrap($qname),
|
|
|
|
),
|
|
|
|
Self::RecoverEleIgnore_(name, ..) => write!(
|
|
|
|
f,
|
|
|
|
"attempting to recover by ignoring element \
|
|
|
|
with unexpected name {given} \
|
|
|
|
(expected {expected})",
|
|
|
|
given = TtQuote::wrap(name),
|
|
|
|
expected = TtQuote::wrap($qname),
|
|
|
|
),
|
|
|
|
|
|
|
|
Self::Attrs_(sa) => todo!("Attrs_ Display: {sa:?}"),
|
|
|
|
Self::Closed_(_) => write!(
|
|
|
|
f,
|
|
|
|
"element {} closed",
|
|
|
|
TtQuote::wrap($qname)
|
|
|
|
),
|
|
|
|
$(
|
|
|
|
Self::$ntref(st) => std::fmt::Display::fmt(st, f),
|
|
|
|
)*
|
|
|
|
todo => todo!("other Display: {todo:?}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq)]
|
|
|
|
enum [<$nt Error_>] {
|
|
|
|
UnexpectedEle_(crate::xir::QName, crate::span::Span),
|
|
|
|
Attrs_(crate::xir::parse::AttrParseError<[<$nt AttrsState_>]>),
|
|
|
|
$(
|
|
|
|
$ntref([<$ntref Error_>]),
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<crate::xir::parse::AttrParseError<[<$nt AttrsState_>]>>
|
|
|
|
for [<$nt Error_>]
|
|
|
|
{
|
|
|
|
fn from(
|
|
|
|
e: crate::xir::parse::AttrParseError<[<$nt AttrsState_>]>
|
|
|
|
) -> Self {
|
|
|
|
[<$nt Error_>]::Attrs_(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$(
|
|
|
|
impl From<[<$ntref Error_>]> for [<$nt Error_>] {
|
|
|
|
fn from(e: [<$ntref Error_>]) -> Self {
|
|
|
|
[<$nt Error_>]::$ntref(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
|
|
|
|
impl std::error::Error for [<$nt Error_>] {
|
|
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
|
|
// TODO
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Display for [<$nt Error_>] {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
use crate::{
|
|
|
|
fmt::DisplayWrapper,
|
|
|
|
xir::fmt::TtOpenXmlEle,
|
|
|
|
};
|
|
|
|
|
|
|
|
match self {
|
|
|
|
Self::UnexpectedEle_(name, _) => {
|
|
|
|
write!(f, "unexpected {}", TtOpenXmlEle::wrap(name))
|
|
|
|
}
|
|
|
|
Self::Attrs_(e) => std::fmt::Display::fmt(e, f),
|
|
|
|
$(
|
|
|
|
Self::$ntref(e) => std::fmt::Display::fmt(e, f),
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl crate::diagnose::Diagnostic for [<$nt Error_>] {
|
|
|
|
fn describe(&self) -> Vec<crate::diagnose::AnnotatedSpan> {
|
|
|
|
todo!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl crate::parse::ParseState for $nt {
|
|
|
|
type Token = crate::xir::flat::XirfToken;
|
|
|
|
type Object = $objty;
|
|
|
|
type Error = [<$nt Error_>];
|
|
|
|
|
|
|
|
fn parse_token(
|
|
|
|
self,
|
|
|
|
tok: Self::Token,
|
|
|
|
_: crate::parse::NoContext,
|
|
|
|
) -> crate::parse::TransitionResult<Self> {
|
|
|
|
use crate::{
|
2022-07-13 15:02:46 -04:00
|
|
|
parse::{EmptyContext, Transition, Transitionable},
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
xir::{
|
|
|
|
flat::XirfToken,
|
|
|
|
parse::attr::parse_attrs,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
use $nt::{
|
|
|
|
Attrs_, Expecting_, RecoverEleIgnore_,
|
|
|
|
RecoverEleIgnoreClosed_, ExpectClose_, Closed_
|
|
|
|
};
|
|
|
|
|
|
|
|
match (self, tok) {
|
|
|
|
(Expecting_, XirfToken::Open(qname, span, ..)) if qname == $qname => {
|
2022-07-13 23:42:51 -04:00
|
|
|
Transition(Attrs_(parse_attrs(qname, span)))
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
.incomplete()
|
|
|
|
},
|
|
|
|
|
|
|
|
(Expecting_, XirfToken::Open(qname, span, depth)) => {
|
|
|
|
Transition(RecoverEleIgnore_(qname, span, depth)).err(
|
|
|
|
[<$nt Error_>]::UnexpectedEle_(qname, span.name_span())
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
(
|
|
|
|
RecoverEleIgnore_(qname, _, depth_open),
|
|
|
|
XirfToken::Close(_, span, depth_close)
|
|
|
|
) if depth_open == depth_close => {
|
|
|
|
Transition(RecoverEleIgnoreClosed_(qname, span)).incomplete()
|
|
|
|
},
|
|
|
|
|
|
|
|
(st @ RecoverEleIgnore_(..), _) => {
|
|
|
|
Transition(st).incomplete()
|
|
|
|
},
|
|
|
|
|
|
|
|
(Attrs_(sa), tok) => {
|
|
|
|
sa.delegate_until_obj(
|
|
|
|
tok,
|
|
|
|
EmptyContext,
|
|
|
|
|sa| Transition(Attrs_(sa)),
|
|
|
|
|| unreachable!("see ParseState::delegate_until_obj dead"),
|
2022-07-13 23:42:51 -04:00
|
|
|
|#[allow(unused_variables)] sa, attrs| {
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
let obj = match attrs {
|
2022-07-13 23:42:51 -04:00
|
|
|
// Attribute field bindings for `$attrmap`
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
[<$nt Attrs_>] {
|
|
|
|
$(
|
|
|
|
$field,
|
|
|
|
)*
|
2022-07-13 23:42:51 -04:00
|
|
|
} => {
|
|
|
|
// Optional `OpenSpan` binding
|
|
|
|
$(
|
|
|
|
use crate::xir::parse::attr::AttrParseState;
|
|
|
|
let $open_span = sa.element_span();
|
|
|
|
)?
|
|
|
|
|
|
|
|
$attrmap
|
|
|
|
},
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
Transition($ntfirst(Default::default())).ok(obj)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
$(
|
|
|
|
($ntprev(st_inner), tok) => {
|
|
|
|
st_inner.delegate(
|
|
|
|
tok,
|
|
|
|
EmptyContext,
|
|
|
|
|si| Transition($ntprev(si)),
|
|
|
|
|| Transition($ntnext(Default::default()))
|
|
|
|
)
|
|
|
|
},
|
|
|
|
)*
|
|
|
|
|
|
|
|
// XIRF ensures proper nesting,
|
|
|
|
// so this must be our own closing tag.
|
2022-07-13 23:42:51 -04:00
|
|
|
(ExpectClose_(_), XirfToken::Close(_, span, _)) => {
|
|
|
|
$(
|
|
|
|
let $close_span = span;
|
|
|
|
)?
|
|
|
|
$closemap.transition(Closed_(span.tag_span()))
|
|
|
|
},
|
tamer: xir::parse::ele: Initial element parser generator concept
This begins generating parsers that are capable of parsing elements. I need
to move on, so this abstraction isn't going to go as far as it could, but
let's see where it takes me.
This was the work that required the recent lookahead changes, which has been
detailed in previous commits.
This initial support is basic, but robust. It supports parsing elements
with attributes and children, but it does not yet support the equivalent of
the Kleene star (`*`). Such support will likely be added by supporting
parsers that are able to recurse on their own definition in tail position,
which will also require supporting parsers that do not add to the stack.
This generates parsers that, like all the other parsers, use enums to
provide a typed stack. Stitched parsers produce a nested stack that is
always bounded in size. Fortunately, expressions---which can nest
deeply---do not need to maintain ancestor context on the stack, and so this
should work fine; we can get away with this because XIRF ensures proper
nesting for us. Statements that _do_ need to maintain such context are not
nested.
This also does not yet support emitting an object on closing tag, which
will be necessary for NIR, which will be a streaming IR that is "near" to
the source XML in structure. This will then be used to lower into AIR for
the ASG, which gives structure needed for further analysis.
More information to come; I just want to get this committed to serve as a
mental synchronization point and clear my head, since I've been sitting on
these changes for so long and have to keep stashing them as I tumble down
rabbit holes covered in yak hair.
DEV-7145
2022-07-13 13:55:32 -04:00
|
|
|
|
|
|
|
// TODO: Use `is_accepting` guard if we do not utilize
|
|
|
|
// exhaustiveness check.
|
|
|
|
(st @ (Closed_(..) | RecoverEleIgnoreClosed_(..)), tok) =>
|
|
|
|
Transition(st).dead(tok),
|
|
|
|
|
|
|
|
todo => todo!("{todo:?}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_accepting(&self) -> bool {
|
|
|
|
matches!(*self, Self::Closed_(..) | Self::RecoverEleIgnoreClosed_(..))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
(@!ele_dfn_sum $nt:ident [$($ntref:ident)*]) => {
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
|
|
enum $nt {
|
|
|
|
$(
|
|
|
|
$ntref($ntref),
|
|
|
|
)*
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test;
|