logic_parser/parsing/
node.rs1use std::collections::HashSet;
2
3#[cfg(feature = "serde")]
4use serde::{Serialize, Deserialize};
5
6#[cfg(feature = "serde")]
7#[derive(Debug, Serialize, Deserialize)]
8#[serde(tag = "type", rename_all="snake_case")]
9pub enum ASTNode {
10 Identifier { name: String },
11 Literal { value: bool },
12 #[serde(rename = "operator.not")]
13 Not { operand: Box<ASTNode> },
14 #[serde(rename = "operator.and")]
15 And { left: Box<ASTNode>, right: Box<ASTNode> },
16 #[serde(rename = "operator.or")]
17 Or { left: Box<ASTNode>, right: Box<ASTNode> },
18 #[serde(rename = "operator.implies")]
19 Implies { left: Box<ASTNode>, right: Box<ASTNode> },
20 #[serde(rename = "operator.iff")]
21 IfAndOnlyIf { left: Box<ASTNode>, right: Box<ASTNode> },
22}
23
24#[cfg(not(feature = "serde"))]
28#[derive(Debug)]
29pub enum ASTNode {
30 Identifier { name: String },
31 Literal { value: bool },
32 Not { operand: Box<ASTNode> },
33 And { left: Box<ASTNode>, right: Box<ASTNode> },
34 Or { left: Box<ASTNode>, right: Box<ASTNode> },
35 Implies { left: Box<ASTNode>, right: Box<ASTNode> },
36 IfAndOnlyIf { left: Box<ASTNode>, right: Box<ASTNode> },
37}
38
39impl ASTNode {
40 pub fn as_string(&self) -> String {
41 format!("{:#?}", self)
42 }
43
44 pub fn repr(&self) -> &str {
45 match self {
46 ASTNode::Identifier { name } => name,
47 ASTNode::Literal { value } => if *value { "1" } else { "0" },
48 ASTNode::Not { .. } => "¬",
49 ASTNode::And { .. } => "∧",
50 ASTNode::Or { .. } => "∨",
51 ASTNode::Implies { .. } => "⇒",
52 ASTNode::IfAndOnlyIf { .. } => "⟷",
53 }
54 }
55
56 pub fn get_identifiers(&self) -> HashSet<&str> {
60 let mut variables = HashSet::new();
61 match self {
62 ASTNode::Identifier { name } => {
63 variables.insert(name.as_str());
64 },
65 ASTNode::Literal { .. } => {},
66 ASTNode::Not { operand } => {
67 variables.extend(operand.get_identifiers());
68 },
69 ASTNode::And { left, right } => {
70 variables.extend(left.get_identifiers());
71 variables.extend(right.get_identifiers());
72 },
73 ASTNode::Or { left, right } => {
74 variables.extend(left.get_identifiers());
75 variables.extend(right.get_identifiers());
76 },
77 ASTNode::Implies { left, right } => {
78 variables.extend(left.get_identifiers());
79 variables.extend(right.get_identifiers());
80 },
81 ASTNode::IfAndOnlyIf { left, right } => {
82 variables.extend(left.get_identifiers());
83 variables.extend(right.get_identifiers());
84 }
85 }
86 variables
87 }
88
89 #[cfg(not(feature = "serde"))]
90 pub fn as_json(&self) -> String {
91 match self {
92 ASTNode::Identifier { name } => {
93 format!(r###"{{
94 "type": "identifier",
95 "name": "{name}"
96 }}"###)
97 },
98 ASTNode::Literal { value } => {
99 format!(r###"{{
100 "type": "literal",
101 "value": {value}
102 }}"###)
103 },
104 ASTNode::Not { operand } => {
105 format!(r###"{{
106 "type": "operator.not",
107 "operand": {operand}
108 }}"###, operand=operand.as_json())
109 },
110 ASTNode::And { left, right } => {
111 format!(r###"{{
112 "type": "operator.and",
113 "left": {left},
114 "right": {right}
115 }}"###, left=left.as_json(), right=right.as_json())
116 },
117 ASTNode::Or { left, right } => {
118 format!(r###"{{
119 "type": "operator.or",
120 "left": {left},
121 "right": {right}
122 }}"###, left=left.as_json(), right=right.as_json())
123 },
124 ASTNode::Implies { left, right } => {
125 format!(r###"{{
126 "type": "operator.implies",
127 "left": {left},
128 "right": {right}
129 }}"###, left=left.as_json(), right=right.as_json())
130 },
131 ASTNode::IfAndOnlyIf { left, right } => {
132 format!(r###"{{
133 "type": "operator.iff",
134 "left": {left},
135 "right": {right}
136 }}"###, left=left.as_json(), right=right.as_json())
137 }
138 }
139 }
140
141 #[cfg(feature = "serde")]
142 pub fn as_json(&self) -> String {
143 serde_json::to_string(self).unwrap()
144 }
145}