Skip to main content

textlane_core/models/
nlcst.rs

1use crate::ArenaVec;
2use crate::models::data::Data;
3use crate::models::position::Position;
4
5/// An nlcst node: natural language as paragraphs, sentences and words.
6#[derive(Debug, PartialEq)]
7pub enum Node<'a> {
8    Root(Parent<'a>),
9    Paragraph(Parent<'a>),
10    Sentence(Parent<'a>),
11    Word(Parent<'a>),
12    Text(Literal<'a>),
13    Symbol(Literal<'a>),
14    Punctuation(Literal<'a>),
15    WhiteSpace(Literal<'a>),
16    Source(Literal<'a>),
17    Unknown(Unknown<'a>),
18}
19
20/// A node with children: a root, paragraph, sentence or word.
21#[derive(Debug, PartialEq)]
22pub struct Parent<'a> {
23    pub children: ArenaVec<'a, Node<'a>>,
24    pub position: Option<Position<'a>>,
25    /// unist's `data`, when the node carries any.
26    pub data: Option<&'a Data<'a>>,
27}
28
29/// A node with a value: text, a symbol, punctuation, white space or source.
30#[derive(Debug, PartialEq)]
31pub struct Literal<'a> {
32    pub value: &'a str,
33    pub position: Option<Position<'a>>,
34    /// unist's `data`, when the node carries any.
35    pub data: Option<&'a Data<'a>>,
36}
37
38/// A node of a type nlcst does not define.
39#[derive(Debug, PartialEq)]
40pub struct Unknown<'a> {
41    /// The node's `type`.
42    pub kind: &'a str,
43    /// Its fields besides `type`, `children`, `position` and `data`, in order.
44    pub fields: &'a [(&'a str, Data<'a>)],
45    /// Its children, when it is a parent.
46    pub children: Option<ArenaVec<'a, Node<'a>>>,
47    pub position: Option<Position<'a>>,
48    /// unist's `data`, when the node carries any.
49    pub data: Option<&'a Data<'a>>,
50}
51
52impl<'a> Node<'a> {
53    /// The node's nlcst `type`, as JSON writes it (`WordNode`).
54    pub fn kind(&self) -> &'a str {
55        match self {
56            Node::Root(_) => "RootNode",
57            Node::Paragraph(_) => "ParagraphNode",
58            Node::Sentence(_) => "SentenceNode",
59            Node::Word(_) => "WordNode",
60            Node::Text(_) => "TextNode",
61            Node::Symbol(_) => "SymbolNode",
62            Node::Punctuation(_) => "PunctuationNode",
63            Node::WhiteSpace(_) => "WhiteSpaceNode",
64            Node::Source(_) => "SourceNode",
65            Node::Unknown(node) => node.kind,
66        }
67    }
68
69    /// The node's children, when it is a parent.
70    pub fn children(&self) -> Option<&ArenaVec<'a, Node<'a>>> {
71        match self {
72            Node::Root(node)
73            | Node::Paragraph(node)
74            | Node::Sentence(node)
75            | Node::Word(node) => Some(&node.children),
76            Node::Unknown(node) => node.children.as_ref(),
77            _ => None,
78        }
79    }
80
81    /// The node's value, when it is a literal.
82    pub fn value(&self) -> Option<&'a str> {
83        match self {
84            Node::Text(node)
85            | Node::Symbol(node)
86            | Node::Punctuation(node)
87            | Node::WhiteSpace(node)
88            | Node::Source(node) => Some(node.value),
89            _ => None,
90        }
91    }
92
93    /// The node's unist `data`, when it carries any.
94    pub fn data(&self) -> Option<&'a Data<'a>> {
95        match self {
96            Node::Root(node)
97            | Node::Paragraph(node)
98            | Node::Sentence(node)
99            | Node::Word(node) => node.data,
100            Node::Text(node)
101            | Node::Symbol(node)
102            | Node::Punctuation(node)
103            | Node::WhiteSpace(node)
104            | Node::Source(node) => node.data,
105            Node::Unknown(node) => node.data,
106        }
107    }
108
109    pub fn position(&self) -> Option<&Position<'a>> {
110        match self {
111            Node::Root(node)
112            | Node::Paragraph(node)
113            | Node::Sentence(node)
114            | Node::Word(node) => node.position.as_ref(),
115            Node::Text(node)
116            | Node::Symbol(node)
117            | Node::Punctuation(node)
118            | Node::WhiteSpace(node)
119            | Node::Source(node) => node.position.as_ref(),
120            Node::Unknown(node) => node.position.as_ref(),
121        }
122    }
123}