use crate::{
BadDeclaration, Block, Cursor, CursorSink, DeclarationValue, Diagnostic, Kind, KindSet, NodeMetadata,
NodeWithMetadata, Parse, Parser, Peek, Result, SemanticEq, Span, State, T, ToCursors, ToSpan,
};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(
feature = "serde",
serde(bound(serialize = "P: serde::Serialize, D: serde::Serialize, R: serde::Serialize"))
)]
pub struct QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M>,
M: NodeMetadata,
{
pub prelude: P,
pub block: Block<'a, D, R, M>,
#[cfg_attr(feature = "serde", serde(skip))]
meta: M,
}
impl<'a, P, D, R, M> NodeWithMetadata<M> for QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M>,
M: NodeMetadata,
{
fn metadata(&self) -> M {
self.meta
}
}
impl<'a, P, D, R, M> Peek<'a> for QualifiedRule<'a, P, D, R, M>
where
P: Peek<'a>,
D: DeclarationValue<'a, M>,
M: NodeMetadata,
{
fn peek<Iter>(p: &Parser<'a, Iter>, c: Cursor) -> bool
where
Iter: Iterator<Item = crate::Cursor> + Clone,
{
<P>::peek(p, c)
}
}
impl<'a, P, D, R, M> Parse<'a> for QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M>,
P: Parse<'a>,
R: Parse<'a> + NodeWithMetadata<M> + crate::RuleVariants<'a, DeclarationValue = D, Metadata = M>,
M: NodeMetadata,
{
fn parse<Iter>(p: &mut Parser<'a, Iter>) -> Result<Self>
where
Iter: Iterator<Item = crate::Cursor> + Clone,
{
let c = p.peek_n(1);
if p.at_end() {
Err(Diagnostic::new(p.peek_n(1), Diagnostic::unexpected_end))?
}
if p.is(State::Nested) && <T!['}']>::peek(p, c) {
Err(Diagnostic::new(c, Diagnostic::unexpected_close_curly))?;
}
let checkpoint = p.checkpoint();
if <T![DashedIdent]>::peek(p, c) {
p.parse::<T![DashedIdent]>().ok();
if <T![:]>::peek(p, p.peek_n(1)) {
if p.is(State::Nested) {
p.rewind(checkpoint.clone());
let start = p.peek_n(1);
p.parse::<BadDeclaration>()?;
let end = p.peek_n(0);
Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
} else {
p.parse::<Block<'a, D, R, M>>()?;
let start = p.peek_n(1);
p.parse::<BadDeclaration>()?;
let end = p.peek_n(0);
Err(Diagnostic::new(start, Diagnostic::bad_declaration).with_end_cursor(end))?
}
}
p.rewind(checkpoint);
}
let old_stop = p.set_stop(KindSet::new(&[Kind::LeftCurly]));
let prelude = p.parse::<P>();
p.set_stop(old_stop);
let prelude = prelude?;
let block = p.parse::<Block<'a, D, R, M>>()?;
let meta = block.metadata();
Ok(Self { prelude, block, meta })
}
}
impl<'a, P, D, R, M> ToCursors for QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M> + ToCursors,
P: ToCursors,
R: ToCursors,
M: NodeMetadata,
{
fn to_cursors(&self, s: &mut impl CursorSink) {
ToCursors::to_cursors(&self.prelude, s);
ToCursors::to_cursors(&self.block, s);
}
}
impl<'a, P, D, R, M> ToSpan for QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M> + ToSpan,
P: ToSpan,
R: ToSpan,
M: NodeMetadata,
{
fn to_span(&self) -> Span {
self.prelude.to_span() + self.block.to_span()
}
}
impl<'a, P, D, R, M> SemanticEq for QualifiedRule<'a, P, D, R, M>
where
D: DeclarationValue<'a, M> + SemanticEq,
P: SemanticEq,
R: SemanticEq,
M: NodeMetadata,
{
fn semantic_eq(&self, other: &Self) -> bool {
self.prelude.semantic_eq(&other.prelude) && self.block.semantic_eq(&other.block)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{EmptyAtomSet, test_helpers::*};
#[derive(Debug)]
struct Decl(T![Ident]);
impl NodeWithMetadata<()> for Decl {
fn metadata(&self) {}
}
impl<'a> DeclarationValue<'a, ()> for Decl {
type ComputedValue = T![Eof];
fn is_initial(&self) -> bool {
false
}
fn is_inherit(&self) -> bool {
false
}
fn is_unset(&self) -> bool {
false
}
fn is_revert(&self) -> bool {
false
}
fn is_revert_layer(&self) -> bool {
false
}
fn needs_computing(&self) -> bool {
false
}
fn parse_specified_declaration_value<Iter>(p: &mut Parser<'a, Iter>, _: Cursor) -> Result<Self>
where
Iter: Iterator<Item = crate::Cursor> + Clone,
{
p.parse::<T![Ident]>().map(Self)
}
}
impl ToCursors for Decl {
fn to_cursors(&self, s: &mut impl CursorSink) {
ToCursors::to_cursors(&self.0, s);
}
}
impl ToSpan for Decl {
fn to_span(&self) -> Span {
self.0.to_span()
}
}
impl SemanticEq for Decl {
fn semantic_eq(&self, other: &Self) -> bool {
self.0.semantic_eq(&other.0)
}
}
#[derive(Debug)]
struct Rule(T![Ident]);
impl<'a> Parse<'a> for Rule {
fn parse<I>(p: &mut Parser<'a, I>) -> Result<Self>
where
I: Iterator<Item = Cursor> + Clone,
{
Ok(Self(p.parse::<T![Ident]>()?))
}
}
impl ToCursors for Rule {
fn to_cursors(&self, s: &mut impl CursorSink) {
ToCursors::to_cursors(&self.0, s);
}
}
impl ToSpan for Rule {
fn to_span(&self) -> Span {
self.0.to_span()
}
}
impl NodeWithMetadata<()> for Rule {
fn metadata(&self) {}
}
impl<'a> crate::RuleVariants<'a> for Rule {
type DeclarationValue = Decl;
type Metadata = ();
}
#[test]
fn size_test() {
assert_eq!(std::mem::size_of::<QualifiedRule<T![Ident], Decl, Rule, ()>>(), 112);
}
#[test]
fn test_writes() {
assert_parse!(EmptyAtomSet::ATOMS, QualifiedRule<T![Ident], Decl, Rule, ()>, "body{color:black}");
}
}