1use std::fmt::{Display, Formatter};
2
3use derive_more::From;
4
5use crate::Number;
6
7#[derive(Debug, Clone, Eq, PartialEq, Hash)]
8pub struct Identifier(pub String);
9
10impl Display for Identifier {
11 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
12 f.write_str(&self.0)
13 }
14}
15
16#[derive(Debug, Copy, Clone, Eq, PartialEq)]
17pub enum UnaryOp {
18 Plus,
19 Minus,
20}
21
22#[derive(Debug, Copy, Clone, Eq, PartialEq)]
23pub enum BinaryArithmeticOp {
24 Add,
25 Subtract,
26 Multiply,
27 Divide,
28 Modulo,
29}
30
31#[derive(Debug, Copy, Clone, Eq, PartialEq)]
32pub enum BinaryOp {
33 Arithmetic(BinaryArithmeticOp),
34 Alt,
35 And,
36 Or,
37}
38
39#[derive(Debug, Copy, Clone, Eq, PartialEq)]
40pub enum UpdateOp {
41 Arithmetic(BinaryArithmeticOp),
42 Alt,
43 Modify,
44 Assign,
45}
46
47#[derive(Debug, Copy, Clone, Eq, PartialEq)]
48pub enum Comparator {
49 Eq,
50 Neq,
51 Gt,
52 Ge,
53 Lt,
54 Le,
55}
56
57#[derive(Debug, Clone, Eq, PartialEq)]
58pub enum Suffix {
59 Optional,
61 Iterate,
63 Index(Identifier),
65 Query(Box<Query>),
67 Slice(Option<Box<Query>>, Option<Box<Query>>),
69}
70
71#[derive(Debug, Clone, Eq, PartialEq)]
72pub enum StringFragment {
73 String(String),
74 Query(Query),
75}
76
77#[derive(Debug, Clone, Eq, PartialEq)]
78pub enum ObjectBindPatternEntry {
79 KeyOnly(Identifier),
81 ValueOnly(Box<Query>, Box<BindPattern>),
83 KeyAndValue(Identifier, Box<BindPattern>),
85}
86
87#[derive(Debug, Clone, Eq, PartialEq)]
88pub enum BindPattern {
89 Variable(Identifier),
91 Array(Vec<BindPattern>),
93 Object(Vec<ObjectBindPatternEntry>),
95}
96
97#[derive(Debug, Clone, Eq, PartialEq)]
98pub enum FuncArg {
99 Variable(Identifier),
100 Closure(Identifier),
101}
102
103#[derive(Debug, Clone, Eq, PartialEq)]
104pub struct FuncDef {
105 pub name: Identifier,
106 pub args: Vec<FuncArg>,
107 pub body: Box<Query>,
108}
109
110#[derive(Debug, Clone, Eq, PartialEq)]
111pub enum Term {
112 Constant(ConstantPrimitive),
114 String(Vec<StringFragment>),
116
117 Identity,
119 Recurse,
121 Suffix(Box<Term>, Suffix),
130
131 Variable(Identifier),
133 FunctionCall { name: Identifier, args: Vec<Query> },
135 Format(Identifier, Option<Vec<StringFragment>>),
137 Query(Box<Query>),
139 Unary(UnaryOp, Box<Term>),
141 Object(Vec<(Query, Option<Query>)>),
143 Array(Option<Box<Query>>),
145 Break(Identifier),
147}
148
149#[derive(Debug, Clone, Eq, PartialEq)]
150pub enum Query {
151 Term(Box<Term>),
153 WithFunc {
155 function: FuncDef,
156 query: Box<Query>,
157 },
158 Pipe { lhs: Box<Query>, rhs: Box<Query> },
160 Concat { lhs: Box<Query>, rhs: Box<Query> },
162 Bind {
164 source: Box<Term>,
165 patterns: Vec<BindPattern>,
166 body: Box<Query>,
167 },
168 Reduce {
170 source: Box<Term>,
171 pattern: BindPattern,
172 initial: Box<Query>,
173 accumulator: Box<Query>,
174 },
175 ForEach {
177 source: Box<Term>,
178 pattern: BindPattern,
179 initial: Box<Query>,
180 update: Box<Query>,
181 extract: Option<Box<Query>>,
182 },
183 If {
185 cond: Box<Query>,
186 positive: Box<Query>,
187 negative: Option<Box<Query>>,
188 },
189 Try {
191 body: Box<Query>,
192 catch: Option<Box<Query>>,
193 },
194 Label { label: Identifier, body: Box<Query> },
196
197 Operate {
199 lhs: Box<Query>,
200 operator: BinaryOp,
201 rhs: Box<Query>,
202 },
203 Update {
205 lhs: Box<Query>,
206 operator: UpdateOp,
207 rhs: Box<Query>,
208 },
209 Compare {
211 lhs: Box<Query>,
212 comparator: Comparator,
213 rhs: Box<Query>,
214 },
215}
216
217#[derive(Debug, Clone, Eq, PartialEq)]
218pub enum ConstantPrimitive {
219 Null,
220 False,
221 True,
222 Number(Number),
223 String(String),
224}
225
226#[derive(Debug, Clone, Eq, PartialEq, From)]
227pub enum ConstantValue {
228 Primitive(ConstantPrimitive),
229 Array(ConstantArray),
230 Object(ConstantObject),
231}
232
233#[derive(Debug, Clone, Eq, PartialEq, Default)]
234pub struct ConstantArray(pub Vec<ConstantValue>);
235
236#[derive(Debug, Clone, Eq, PartialEq, Default)]
237pub struct ConstantObject(pub Vec<(String, ConstantValue)>);
238
239#[derive(Debug, Clone, Eq, PartialEq)]
240pub struct Import {
241 pub path: String,
242 pub alias: Option<Identifier>,
243 pub meta: Option<ConstantObject>,
244}
245
246#[derive(Debug, Clone, Eq, PartialEq)]
247pub struct Program {
248 pub module_header: Option<ConstantObject>,
249 pub imports: Vec<Import>,
250 pub functions: Vec<FuncDef>,
251 pub query: Query,
252}
253
254impl From<&str> for Identifier {
255 fn from(s: &str) -> Self {
256 Self(s.to_string())
257 }
258}
259
260impl From<Term> for Query {
261 fn from(term: Term) -> Self {
262 if let Term::Query(query) = term {
263 *query
264 } else {
265 Query::Term(Box::new(term))
266 }
267 }
268}
269
270impl From<Query> for Term {
271 fn from(query: Query) -> Self {
272 if let Query::Term(term) = query {
273 *term
274 } else {
275 Term::Query(Box::new(query))
276 }
277 }
278}