tamer: ir::xir::tree: Extract Attr{,List} into new module
The `tree` module is getting more difficult to navigate. The tests still remain where they were, since a bunch of concerns are mixed together. Any tests specific only to this module will be added here.main
parent
fe7b64fe62
commit
a5afc76568
|
@ -397,8 +397,9 @@ pub enum Token<Ix: SymbolIndexSize> {
|
|||
/// having to copy values.
|
||||
/// The last fragment must be a [`Token::AttrValue`].
|
||||
///
|
||||
/// This is intended for writing to a token stream and may not be
|
||||
/// emitted by readers or supported by [XIR Tree](self::tree).
|
||||
/// Since each fragment contains a span,
|
||||
/// this also potentially gives higher resolution for the origin of
|
||||
/// components of generated attribute values.
|
||||
AttrValueFragment(AttrValue<Ix>, Span),
|
||||
|
||||
/// Comment node.
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! XIR token stream parsed into a tree-based IR.
|
||||
//! XIR token stream parsed into a tree-based IR (XIRT).
|
||||
//!
|
||||
//! **This is a work-in-progress implementation.**
|
||||
//! It will be augmented only as needed.
|
||||
|
@ -172,7 +172,10 @@ use super::{AttrValue, QName, Token};
|
|||
use crate::{span::Span, sym::SymbolIndexSize};
|
||||
use std::{fmt::Display, mem::take};
|
||||
|
||||
/// A XIR tree.
|
||||
mod attr;
|
||||
pub use attr::{Attr, AttrList};
|
||||
|
||||
/// A XIR tree (XIRT).
|
||||
///
|
||||
/// This object represents a XIR token stream parsed into a tree
|
||||
/// representation.
|
||||
|
@ -201,45 +204,6 @@ impl<Ix: SymbolIndexSize> Tree<Ix> {
|
|||
}
|
||||
}
|
||||
|
||||
/// List of attributes.
|
||||
///
|
||||
/// Attributes are ordered in XIR so that this IR will be suitable for code
|
||||
/// formatters and linters.
|
||||
///
|
||||
/// This abstraction will allow us to manipulate the internal data so that
|
||||
/// it is suitable for a particular task in the future
|
||||
/// (e.g. O(1) lookups by attribute name).
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||
pub struct AttrList<Ix: SymbolIndexSize> {
|
||||
attrs: Vec<Attr<Ix>>,
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize> AttrList<Ix> {
|
||||
/// Construct a new, empty attribute list.
|
||||
pub fn new() -> Self {
|
||||
Self { attrs: vec![] }
|
||||
}
|
||||
|
||||
/// Add an attribute to the end of the attribute list.
|
||||
pub fn push(&mut self, attr: Attr<Ix>) {
|
||||
self.attrs.push(attr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize> From<Vec<Attr<Ix>>> for AttrList<Ix> {
|
||||
fn from(attrs: Vec<Attr<Ix>>) -> Self {
|
||||
AttrList { attrs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize, const N: usize> From<[Attr<Ix>; N]> for AttrList<Ix> {
|
||||
fn from(attrs: [Attr<Ix>; N]) -> Self {
|
||||
AttrList {
|
||||
attrs: attrs.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Element node.
|
||||
///
|
||||
/// This represents an [XML element] beginning with an opening tag that is
|
||||
|
@ -290,21 +254,6 @@ impl<Ix: SymbolIndexSize> Element<Ix> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Element attribute.
|
||||
///
|
||||
/// Attributes in [`Tree`] may stand alone without an element context to
|
||||
/// permit selective parsing of XIR token streams.
|
||||
///
|
||||
/// TODO: This doesn't yet handle whitespace for alignment of attributes;
|
||||
/// deferring this until it's actually needed.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Attr<Ix: SymbolIndexSize> {
|
||||
name: QName<Ix>,
|
||||
value: AttrValue<Ix>,
|
||||
/// Spans for the attribute name and value respectively.
|
||||
span: (Span, Span),
|
||||
}
|
||||
|
||||
/// A [`Stack`] representing an element and its (optional) parent's stack.
|
||||
///
|
||||
/// Storing the parent of an [`Element`] allows it to be manipulated on the
|
||||
|
@ -519,11 +468,11 @@ impl<Ix: SymbolIndexSize> Stack<Ix> {
|
|||
fn close_attr(self, value: AttrValue<Ix>, span: Span) -> Result<Self, Ix> {
|
||||
Ok(match self {
|
||||
Self::AttrName(ele_stack, name, open_span) => {
|
||||
Stack::BuddingElement(ele_stack.consume_attr(Attr {
|
||||
Stack::BuddingElement(ele_stack.consume_attr(Attr::new(
|
||||
name,
|
||||
value,
|
||||
span: (open_span, span),
|
||||
}))
|
||||
(open_span, span),
|
||||
)))
|
||||
}
|
||||
_ => todo! {},
|
||||
})
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// XIRT attributes
|
||||
//
|
||||
// Copyright (C) 2014-2021 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/>.
|
||||
|
||||
//! XIRT attributes.
|
||||
//!
|
||||
//! See [parent module](super) for documentation.
|
||||
|
||||
use super::{AttrValue, QName};
|
||||
use crate::{span::Span, sym::SymbolIndexSize};
|
||||
|
||||
/// Element attribute.
|
||||
///
|
||||
/// TODO: This doesn't yet handle whitespace for alignment of attributes;
|
||||
/// deferring this until it's actually needed.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Attr<Ix: SymbolIndexSize> {
|
||||
name: QName<Ix>,
|
||||
value: AttrValue<Ix>,
|
||||
/// Spans for the attribute name and value respectively.
|
||||
span: (Span, Span),
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize> Attr<Ix> {
|
||||
/// Construct a new simple attribute with a name, value, and respective
|
||||
/// [`Span`]s.
|
||||
#[inline]
|
||||
pub fn new(
|
||||
name: QName<Ix>,
|
||||
value: AttrValue<Ix>,
|
||||
span: (Span, Span),
|
||||
) -> Self {
|
||||
Attr { name, value, span }
|
||||
}
|
||||
}
|
||||
|
||||
/// List of attributes.
|
||||
///
|
||||
/// Attributes are ordered in XIR so that this IR will be suitable for code
|
||||
/// formatters and linters.
|
||||
///
|
||||
/// This abstraction will allow us to manipulate the internal data so that
|
||||
/// it is suitable for a particular task in the future
|
||||
/// (e.g. O(1) lookups by attribute name).
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||
pub struct AttrList<Ix: SymbolIndexSize> {
|
||||
attrs: Vec<Attr<Ix>>,
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize> AttrList<Ix> {
|
||||
/// Construct a new, empty attribute list.
|
||||
pub fn new() -> Self {
|
||||
Self { attrs: vec![] }
|
||||
}
|
||||
|
||||
/// Add an attribute to the end of the attribute list.
|
||||
pub fn push(&mut self, attr: Attr<Ix>) {
|
||||
self.attrs.push(attr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize> From<Vec<Attr<Ix>>> for AttrList<Ix> {
|
||||
fn from(attrs: Vec<Attr<Ix>>) -> Self {
|
||||
AttrList { attrs }
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ix: SymbolIndexSize, const N: usize> From<[Attr<Ix>; N]> for AttrList<Ix> {
|
||||
fn from(attrs: [Attr<Ix>; N]) -> Self {
|
||||
AttrList {
|
||||
attrs: attrs.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See [`super::test`].
|
|
@ -151,16 +151,8 @@ fn empty_element_with_attrs_from_toks() {
|
|||
let expected = Element {
|
||||
name,
|
||||
attrs: AttrList::from(vec![
|
||||
Attr {
|
||||
name: attr1,
|
||||
value: val1,
|
||||
span: (*S, *S2),
|
||||
},
|
||||
Attr {
|
||||
name: attr2,
|
||||
value: val2,
|
||||
span: (*S, *S2),
|
||||
},
|
||||
Attr::new(attr1, val1, (*S, *S2)),
|
||||
Attr::new(attr2, val2, (*S, *S2)),
|
||||
]),
|
||||
children: vec![],
|
||||
span: (*S, *S2),
|
||||
|
@ -243,11 +235,7 @@ fn element_with_child_with_attributes() {
|
|||
attrs: AttrList::new(),
|
||||
children: vec![Tree::Element(Element {
|
||||
name: child,
|
||||
attrs: AttrList::from([Attr {
|
||||
name: attr,
|
||||
value,
|
||||
span: (*S, *S2),
|
||||
}]),
|
||||
attrs: AttrList::from([Attr::new(attr, value, (*S, *S2))]),
|
||||
children: vec![],
|
||||
span: (*S, *S3),
|
||||
})],
|
||||
|
@ -275,11 +263,7 @@ fn parser_from_filters_incomplete() {
|
|||
|
||||
let expected = Element {
|
||||
name,
|
||||
attrs: AttrList::from([Attr {
|
||||
name: attr,
|
||||
value: val,
|
||||
span: (*S, *S2),
|
||||
}]),
|
||||
attrs: AttrList::from([Attr::new(attr, val, (*S, *S2))]),
|
||||
children: vec![],
|
||||
span: (*S, *S2),
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue