// XIR flat (XIRF)
//
// 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 .
//! Lightly-parsed XIR as a flat stream (XIRF).
//!
//! XIRF lightly parses a raw XIR [`TokenStream`] into a stream of
//! [`Object`]s that are,
//! like a [`TokenStream`],
//! flat in structure.
//! It provides the following features over raw XIR:
//!
//! 1. All closing tags must correspond to a matching opening tag at the
//! same depth;
//! 2. [`Object`] exposes the [`Depth`] of each opening/closing tag;
//! 3. Attribute tokens are parsed into [`Attr`] objects; and
//! 4. Parsing will fail if input ends before all elements have been
//! closed.
//!
//! XIRF lowering does not perform any dynamic memory allocation;
//! maximum element nesting depth is set statically depending on the needs
//! of the caller.
use super::{
parse::{ParseState, ParseStateResult, ParseStatus, ParsedResult},
tree::{
attr::{AttrParseError, AttrParseState},
Attr,
},
QName, Token, TokenStream, Whitespace,
};
use crate::{span::Span, sym::SymbolId};
use arrayvec::ArrayVec;
use std::{error::Error, fmt::Display, mem::replace};
/// Tag nesting depth
/// (`0` represents the root).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Depth(usize);
impl Display for Depth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0, f)
}
}
/// A lightly-parsed XIRF object.
///
/// Certain XIR [`Token`]s are formed into a single object,
/// such as an [`Attr`].
/// Other objects retain the same format as their underlying token,
/// but are still validated to ensure that they are well-formed and that
/// the XML is well-structured.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Object {
/// Opening tag of an element.
Open(QName, Span, Depth),
/// Closing tag of an element.
///
/// If the name is [`None`],
/// then the tag is self-closing.
/// If the name is [`Some`],
/// then the tag is guaranteed to be balanced
/// (matching the depth of its opening tag).
Close(Option, Span, Depth),
/// An attribute and its value.
///
/// The associated [`Span`]s can be found on the enclosed [`Attr`]
/// object.
Attr(Attr),
/// Comment node.
Comment(SymbolId, Span),
/// Character data as part of an element.
///
/// See also [`CData`](Object::CData) variant.
Text(SymbolId, Span),
/// CData node (``).
///
/// _Warning: It is up to the caller to ensure that the string `]]>` is
/// not present in the text!_
/// This is intended for reading existing XML data where CData is
/// already present,
/// not for producing new CData safely!
CData(SymbolId, Span),
/// Similar to `Text`,
/// but intended for use where only whitespace is allowed,
/// such as alignment of attributes.
Whitespace(Whitespace, Span),
}
/// XIRF-compatible attribute parser.
pub trait FlatAttrParseState = ParseState