use crate::{
CursorSink, Declaration, DeclarationValue, Kind, KindSet, NodeMetadata, NodeWithMetadata, Parse, Parser, Peek,
Result, SemanticEq, Span, T, ToCursors, ToSpan, token_macros,
};
use bumpalo::collections::Vec;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(bound(serialize = "V: serde::Serialize")))]
pub struct DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M>,
M: NodeMetadata,
{
pub open_curly: token_macros::LeftCurly,
pub declarations: Vec<'a, Declaration<'a, V, M>>,
pub close_curly: Option<token_macros::RightCurly>,
#[cfg_attr(feature = "serde", serde(skip))]
meta: M,
}
impl<'a, V, M> NodeWithMetadata<M> for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M>,
M: NodeMetadata,
{
fn metadata(&self) -> M {
self.meta
}
}
impl<'a, V, M> Peek<'a> for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M>,
M: NodeMetadata,
{
const PEEK_KINDSET: KindSet = KindSet::new(&[Kind::LeftCurly]);
}
impl<'a, V, M> Parse<'a> for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M>,
M: NodeMetadata,
{
fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
where
Iter: Iterator<Item = crate::Cursor> + Clone,
{
let open_curly = p.parse::<T!['{']>()?;
let mut declarations = Vec::new_in(p.bump());
let mut meta: M = Default::default();
loop {
if p.at_end() {
meta = meta.with_size(declarations.len().min(u16::MAX as usize) as u16);
return Ok(Self { open_curly, declarations, close_curly: None, meta });
}
let close_curly = p.parse_if_peek::<T!['}']>()?;
if close_curly.is_some() {
meta = meta.with_size(declarations.len().min(u16::MAX as usize) as u16);
return Ok(Self { open_curly, declarations, close_curly, meta });
}
let declaration = p.parse::<Declaration<'a, V, M>>()?;
meta = meta.merge(declaration.metadata());
declarations.push(declaration);
}
}
}
impl<'a, V, M> ToCursors for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M> + ToCursors,
M: NodeMetadata,
{
fn to_cursors(&self, s: &mut impl CursorSink) {
ToCursors::to_cursors(&self.open_curly, s);
ToCursors::to_cursors(&self.declarations, s);
ToCursors::to_cursors(&self.close_curly, s);
}
}
impl<'a, V, M> ToSpan for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M> + ToSpan,
M: NodeMetadata,
{
fn to_span(&self) -> Span {
self.open_curly.to_span()
+ if let Some(close) = self.close_curly { close.to_span() } else { self.declarations.to_span() }
}
}
impl<'a, V, M> SemanticEq for DeclarationList<'a, V, M>
where
V: DeclarationValue<'a, M>,
M: NodeMetadata,
{
fn semantic_eq(&self, other: &Self) -> bool {
self.open_curly.semantic_eq(&other.open_curly)
&& self.declarations.semantic_eq(&other.declarations)
&& self.close_curly.semantic_eq(&other.close_curly)
}
}