1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use std::fmt;

use crate::position::{LexerPosition, NodeSpan};

/// Trait for AST node contents.
///
/// All nodes which will be stored in a [Node] need to implement this.
pub trait NodeContent: fmt::Debug + Clone + PartialEq + Sized {
    /// Convert the contents into a node
    fn into_node<T>(self) -> Node<T>
    where
        T: From<Self> + NodeContent,
    {
        Node::new(self.into(), None)
    }

    /// Add span information to a syntax node
    fn spanned(self, start: LexerPosition, end: LexerPosition) -> Node<Self> {
        assert_eq!(start.source_id, end.source_id);

        Node {
            content: self,
            span: Some(NodeSpan::from_lexer(start, end)),
        }
    }
}

/// A syntax node with span information
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(rserde::Serialize, rserde::Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "rserde"))]
pub struct Node<T: NodeContent> {
    /// Contents of this syntax node
    pub content: T,
    /// Span in the input this node was parsed from
    pub span: Option<NodeSpan>,
}

impl<T: NodeContent> Node<T> {
    /// Create a new syntax node with span information
    pub fn new(content: T, span: Option<NodeSpan>) -> Self {
        Self { content, span }
    }

    /// Return the wrapped syntax node, discarding the span information
    pub fn into_inner(self) -> T {
        self.content
    }

    /// Map this content of this node into a new node
    pub fn map<U: NodeContent>(self, f: impl FnOnce(T) -> U) -> Node<U> {
        Node {
            content: f(self.content),
            span: self.span,
        }
    }

    /// Map this content of this node into a new node with the same span
    pub fn map_spanned<U: NodeContent>(self, f: impl FnOnce(Self) -> U) -> Node<U> {
        let span = self.span;

        Node {
            content: f(self),
            span,
        }
    }
}

impl<T: NodeContent> std::ops::Deref for Node<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.content
    }
}

impl<T: NodeContent> std::ops::DerefMut for Node<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.content
    }
}

// Trivial copy for the node if the wrapped content are Copy
impl<T: NodeContent + Copy> Copy for Node<T> {}

// Display implementation for wrapped node
impl<T: NodeContent + fmt::Display> fmt::Display for Node<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <T as fmt::Display>::fmt(&self.content, f)
    }
}

impl<T: NodeContent> From<T> for Node<T> {
    fn from(inner: T) -> Self {
        Node::new(inner, None)
    }
}

impl NodeContent for &'static str {}

impl<U, T: NodeContent + AsRef<U>> AsRef<U> for Node<T> {
    fn as_ref(&self) -> &U {
        self.content.as_ref()
    }
}

impl<T: NodeContent + PartialEq> PartialEq for Node<T> {
    fn eq(&self, other: &Self) -> bool {
        self.content.eq(&other.content)
    }
}

impl<T: NodeContent + Eq> Eq for Node<T> {}

impl<T: NodeContent + PartialOrd> PartialOrd for Node<T> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.content.partial_cmp(&other.content)
    }
}

impl<T: NodeContent + Ord> Ord for Node<T> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.content.cmp(&other.content)
    }
}

impl<T: NodeContent + std::hash::Hash> std::hash::Hash for Node<T> {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.content.hash(state)
    }
}