unidok-repr 0.2.0

AST and IR for the unidok-parser crate
Documentation
use crate::ast::blocks::{
    BlockAst, CodeBlockAst, Comment, HeadingAst, LinkRefDef, ListAst, QuoteAst, TableAst,
};
use crate::ast::html::{ElemContentAst, HtmlNodeAst};
use crate::ast::macros::{
    BlockMacro, BlockMacroContent, InlineMacroAst, MacroArgs, TokenTree, TokenTreeAtom,
};
use crate::ast::segments::{
    BracesAst, CodeAst, ImageAst, InlineFormatAst, LinkAst, LinkTarget, SegmentAst,
};
use crate::{Span, SyntaxKind, SyntaxSpan};

pub trait ToSpans {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>);
}

impl ToSpans for BlockAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            BlockAst::CodeBlock(c) => c.to_spans(buf),
            BlockAst::Paragraph(p) => p.segments.to_spans(buf),
            BlockAst::Heading(h) => h.to_spans(buf),
            BlockAst::Table(t) => t.to_spans(buf),
            BlockAst::ThematicBreak(_) => {}
            BlockAst::List(l) => l.to_spans(buf),
            BlockAst::Quote(q) => q.to_spans(buf),
            BlockAst::BlockMacro(b) => b.to_spans(buf),
            BlockAst::BlockHtml(h) => h.to_spans(buf),
            BlockAst::Comment(c) => c.to_spans(buf),
            BlockAst::LinkRefDef(l) => l.to_spans(buf),
        }
    }
}

impl ToSpans for SegmentAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            SegmentAst::LineBreak
            | SegmentAst::Text(_)
            | SegmentAst::Text2(_)
            | SegmentAst::Text3(_) => {}
            SegmentAst::Escaped(e) => buf.push(Span::from(e.text).with(SyntaxKind::Escaped)),
            SegmentAst::Substitution(_) => {}
            SegmentAst::Limiter => {}
            SegmentAst::Braces(b) => b.to_spans(buf),
            SegmentAst::Math(_) => {}
            SegmentAst::Link(l) => l.to_spans(buf),
            SegmentAst::Image(i) => i.to_spans(buf),
            SegmentAst::InlineMacro(m) => m.to_spans(buf),
            SegmentAst::InlineHtml(i) => i.to_spans(buf),
            SegmentAst::HtmlEntity(_) => {}
            SegmentAst::Format(f) => f.to_spans(buf),
            SegmentAst::Code(c) => c.to_spans(buf),
        }
    }
}

impl ToSpans for [SegmentAst] {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        for segment in self {
            segment.to_spans(buf)
        }
    }
}

impl ToSpans for [BlockAst] {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        for block in self {
            block.to_spans(buf)
        }
    }
}

impl ToSpans for HeadingAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        self.segments.to_spans(buf);
    }
}

impl ToSpans for Comment {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        buf.push(Span::from(self.content).with(SyntaxKind::Comment));
    }
}

impl ToSpans for CodeBlockAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        buf.push(self.opening_fence.until(self.closing_fence).with(SyntaxKind::CodeBlock));
        buf.push(self.opening_fence.with(SyntaxKind::CodeFence));
        if !self.info.is_empty() {
            buf.push(Span::from(self.info).with(SyntaxKind::InfoString));
        }
        self.lines.to_spans(buf);
        if !self.closing_fence.is_empty() {
            buf.push(self.closing_fence.with(SyntaxKind::CodeFence));
        }
    }
}

impl ToSpans for TableAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        for r in &self.rows {
            for c in &r.cells {
                c.segments.to_spans(buf);
            }
        }
    }
}

impl ToSpans for BlockMacro {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        buf.push(Span::from(self.name).with(SyntaxKind::MacroName));
        if let Some(args) = &self.args {
            args.to_spans(buf);
        }
        match &self.content {
            BlockMacroContent::Prefixed(block) => block.to_spans(buf),
            BlockMacroContent::Braces(blocks) => blocks.to_spans(buf),
            BlockMacroContent::None => {}
        }
    }
}

impl ToSpans for ListAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        for item in &self.items {
            item.to_spans(buf);
        }
    }
}

impl ToSpans for QuoteAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        self.content.to_spans(buf);
    }
}

impl ToSpans for HtmlNodeAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            HtmlNodeAst::Element(e) => {
                if let Some(content) = &e.content {
                    match content {
                        ElemContentAst::Blocks(blocks) => blocks.to_spans(buf),
                        ElemContentAst::Inline(s) => s.to_spans(buf),
                        ElemContentAst::Verbatim(_) => {}
                    }
                }
            }
            HtmlNodeAst::CData(c) => {
                buf.push(Span::from(c.text).with(SyntaxKind::HtmlCdata));
            }
            HtmlNodeAst::Comment(_) => {}
            HtmlNodeAst::Doctype(d) => {
                buf.push(Span::from(d.text).with(SyntaxKind::HtmlCdata));
            }
        }
    }
}

impl ToSpans for LinkRefDef {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        buf.push(Span::from(self.name).with(SyntaxKind::LinkRef));
        buf.push(Span::from(self.url).with(SyntaxKind::LinkHref));
    }
}

impl ToSpans for BracesAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        self.segments.to_spans(buf);
    }
}

impl ToSpans for LinkAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        if let Some(text) = &self.text {
            text.to_spans(buf);
        }

        match self.target {
            LinkTarget::Url { href: _, title: _ } => {}
            LinkTarget::Reference(r) => {
                buf.push(Span::from(r).with(SyntaxKind::LinkRef));
            }
            LinkTarget::Footnote => {}
        }
    }
}

impl ToSpans for ImageAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        if let Some(text) = &self.alt {
            text.to_spans(buf);
        }

        match self.target {
            LinkTarget::Url { href: _, title: _ } => {}
            LinkTarget::Reference(r) => {
                buf.push(Span::from(r).with(SyntaxKind::LinkRef));
            }
            LinkTarget::Footnote => {}
        }
    }
}

impl ToSpans for InlineMacroAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        buf.push(Span::from(self.name).with(SyntaxKind::MacroName));
        if let Some(args) = &self.args {
            args.to_spans(buf);
        }
        self.segment.to_spans(buf);
    }
}

impl ToSpans for InlineFormatAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        self.segments.to_spans(buf);
    }
}

impl ToSpans for CodeAst {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        self.segments.to_spans(buf);
    }
}

impl ToSpans for MacroArgs {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            &MacroArgs::Raw(r) => {
                buf.push(Span::from(r).with(SyntaxKind::MacroArg));
            }
            MacroArgs::TokenTrees(tts) => {
                for tt in tts {
                    tt.to_spans(buf);
                }
            }
        }
    }
}

impl ToSpans for TokenTree {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            TokenTree::Atom(a) => a.to_spans(buf),
            &TokenTree::KV(k, ref v) => {
                buf.push(Span::from(k).with(SyntaxKind::MacroKey));
                v.to_spans(buf);
            }
        }
    }
}

impl ToSpans for TokenTreeAtom {
    fn to_spans(&self, buf: &mut Vec<SyntaxSpan>) {
        match self {
            &TokenTreeAtom::Word(w) => {
                buf.push(Span::from(w).with(SyntaxKind::MacroArg));
            }
            TokenTreeAtom::QuotedWord(_) => {}
            TokenTreeAtom::Tuple(tts) => {
                for tt in tts {
                    tt.to_spans(buf);
                }
            }
            TokenTreeAtom::Braces(b) => b.to_spans(buf),
        }
    }
}