logos_codegen/
leaf.rs

1use std::cmp::{Ord, Ordering};
2use std::fmt::{self, Debug, Display};
3
4use proc_macro2::{Span, TokenStream};
5use syn::{spanned::Spanned, Ident};
6
7use crate::graph::{Disambiguate, Node};
8use crate::util::MaybeVoid;
9
10#[derive(Clone)]
11pub struct Leaf<'t> {
12    pub ident: Option<&'t Ident>,
13    pub span: Span,
14    pub priority: usize,
15    pub field: MaybeVoid,
16    pub callback: Option<Callback>,
17}
18
19#[derive(Clone)]
20pub enum Callback {
21    Label(TokenStream),
22    Inline(Box<InlineCallback>),
23    Skip(Span),
24}
25
26#[derive(Clone)]
27pub struct InlineCallback {
28    pub arg: Ident,
29    pub body: TokenStream,
30    pub span: Span,
31}
32
33impl From<InlineCallback> for Callback {
34    fn from(inline: InlineCallback) -> Callback {
35        Callback::Inline(Box::new(inline))
36    }
37}
38
39impl Callback {
40    pub fn span(&self) -> Span {
41        match self {
42            Callback::Label(tokens) => tokens.span(),
43            Callback::Inline(inline) => inline.span,
44            Callback::Skip(span) => *span,
45        }
46    }
47}
48
49impl<'t> Leaf<'t> {
50    pub fn new(ident: &'t Ident, span: Span) -> Self {
51        Leaf {
52            ident: Some(ident),
53            span,
54            priority: 0,
55            field: MaybeVoid::Void,
56            callback: None,
57        }
58    }
59
60    pub fn new_skip(span: Span) -> Self {
61        Leaf {
62            ident: None,
63            span,
64            priority: 0,
65            field: MaybeVoid::Void,
66            callback: Some(Callback::Skip(span)),
67        }
68    }
69
70    pub fn callback(mut self, callback: Option<Callback>) -> Self {
71        self.callback = callback;
72        self
73    }
74
75    pub fn field(mut self, field: MaybeVoid) -> Self {
76        self.field = field;
77        self
78    }
79
80    pub fn priority(mut self, priority: usize) -> Self {
81        self.priority = priority;
82        self
83    }
84}
85
86impl Disambiguate for Leaf<'_> {
87    fn cmp(left: &Leaf, right: &Leaf) -> Ordering {
88        Ord::cmp(&left.priority, &right.priority)
89    }
90}
91
92impl<'t> From<Leaf<'t>> for Node<Leaf<'t>> {
93    fn from(leaf: Leaf<'t>) -> Self {
94        Node::Leaf(leaf)
95    }
96}
97
98impl Debug for Leaf<'_> {
99    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100        write!(f, "::{}", self)?;
101
102        match self.callback {
103            Some(Callback::Label(ref label)) => write!(f, " ({})", label),
104            Some(Callback::Inline(_)) => f.write_str(" (<inline>)"),
105            Some(Callback::Skip(_)) => f.write_str(" (<skip>)"),
106            None => Ok(()),
107        }
108    }
109}
110
111impl Display for Leaf<'_> {
112    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
113        match self.ident {
114            Some(ident) => Display::fmt(ident, f),
115            None => f.write_str("<skip>"),
116        }
117    }
118}