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
Mike Gerwitz 2021-09-21 10:43:23 -04:00
parent fe7b64fe62
commit a5afc76568
4 changed files with 106 additions and 81 deletions

View File

@ -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.

View File

@ -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! {},
})

View File

@ -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`].

View File

@ -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),
};