1use anyhow::Result;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
5pub struct InnerNode {
6 pub id: String,
7 pub children: Vec<AST>,
8}
9
10#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
11pub struct LeafNode {
12 pub id: String,
13 pub value: String,
14}
15
16#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
17pub enum AST {
18 Document(InnerNode),
19 Stmt(InnerNode),
20 Expr(InnerNode),
21 Angle(InnerNode),
22 Square(InnerNode),
23 Curly(InnerNode),
24 Identifier(InnerNode),
25 Text(LeafNode),
26}
27
28impl AST {
29 pub fn children(&self) -> &Vec<AST> {
30 match self {
31 AST::Document(node)
32 | AST::Stmt(node)
33 | AST::Expr(node)
34 | AST::Angle(node)
35 | AST::Square(node)
36 | AST::Curly(node)
37 | AST::Identifier(node) => &node.children,
38 AST::Text(_) => panic!("Leaf node has no children"),
39 }
40 }
41
42 pub fn value(&self) -> String {
43 match self {
44 AST::Text(leaf) => leaf.value.clone(),
45 AST::Document(_)
46 | AST::Stmt(_)
47 | AST::Expr(_)
48 | AST::Angle(_)
49 | AST::Square(_)
50 | AST::Curly(_)
51 | AST::Identifier(_) => panic!("Inner node has no value"),
52 }
53 }
54
55 pub fn id(&self) -> String {
56 match self {
57 AST::Document(node)
58 | AST::Stmt(node)
59 | AST::Expr(node)
60 | AST::Angle(node)
61 | AST::Square(node)
62 | AST::Curly(node)
63 | AST::Identifier(node) => node.id.clone(),
64 AST::Text(leaf) => leaf.id.clone(),
65 }
66 }
67}
68
69impl AST {
70 pub fn add(&mut self, ast: AST) -> Result<()> {
71 match self {
72 AST::Document(node)
73 | AST::Stmt(node)
74 | AST::Expr(node)
75 | AST::Angle(node)
76 | AST::Square(node)
77 | AST::Curly(node)
78 | AST::Identifier(node) => {
79 node.children.push(ast);
80 }
81 AST::Text(_) => {
82 anyhow::bail!("Cannot add child to leaf node");
83 }
84 }
85 Ok(())
86 }
87
88 pub fn get(&self, id: &str) -> Option<&AST> {
89 match self {
90 AST::Document(node)
91 | AST::Stmt(node)
92 | AST::Expr(node)
93 | AST::Angle(node)
94 | AST::Square(node)
95 | AST::Curly(node)
96 | AST::Identifier(node) => {
97 if node.id == id {
98 return Some(self);
99 }
100 for child in &node.children {
101 if let Some(ast) = child.get(id) {
102 return Some(ast);
103 }
104 }
105 None
106 },
107 AST::Text(node) => {
108 if node.id == id {
109 return Some(self);
110 }
111 None
112 },
113 }
114 }
115}