1#[rust_sitter::grammar("datalog")]
2pub mod datalog {
4 use rust_sitter::Spanned;
5
6 #[rust_sitter::language]
7 #[derive(Debug)]
8 pub struct Program {
9 pub rules: Vec<Declaration>,
10 }
11
12 #[derive(Debug, Clone)]
13 pub enum Declaration {
14 Input(
15 #[rust_sitter::leaf(text = ".input")] (),
16 Spanned<Ident>,
17 RustSnippet,
18 ),
19 Output(
20 #[rust_sitter::leaf(text = ".output")] (),
21 Spanned<Ident>,
22 RustSnippet,
23 ),
24 Persist(#[rust_sitter::leaf(text = ".persist")] (), Spanned<Ident>),
25 Async(
26 #[rust_sitter::leaf(text = ".async")] (),
27 Spanned<Ident>,
28 RustSnippet,
30 RustSnippet,
32 ),
33 Rule(Spanned<Rule>),
34 Static(
35 #[rust_sitter::leaf(text = ".static")] (),
36 Spanned<Ident>,
37 RustSnippet,
38 ),
39 }
40
41 #[derive(Debug, Clone)]
42 pub struct RustSnippet {
43 #[rust_sitter::leaf(text = "`")]
44 _start: (),
45 #[rust_sitter::leaf(pattern = r#"[^`]*"#, transform = |s| s.to_string())]
46 pub code: Spanned<String>,
47 #[rust_sitter::leaf(text = "`")]
48 _end: (),
49 }
50
51 #[derive(Debug, Clone)]
52 pub struct Rule {
53 pub target: TargetRelationExpr,
54
55 pub rule_type: Spanned<RuleType>,
56
57 #[rust_sitter::repeat(non_empty = true)]
58 #[rust_sitter::delimited(
59 #[rust_sitter::leaf(text = ",")]
60 ()
61 )]
62 pub sources: Vec<Atom>,
63
64 #[rust_sitter::leaf(text = ".")]
65 _dot: Option<()>,
66 }
67
68 #[derive(Debug, Clone)]
69 pub enum RuleType {
70 Sync(#[rust_sitter::leaf(text = ":-")] ()),
71 NextTick(#[rust_sitter::leaf(text = ":+")] ()),
72 Async(#[rust_sitter::leaf(text = ":~")] ()),
73 }
74
75 #[derive(Debug, Clone)]
76 pub enum Atom {
77 NegRelation(
78 #[rust_sitter::leaf(text = "!")] (),
79 Spanned<InputRelationExpr>,
80 ),
81 PosRelation(Spanned<InputRelationExpr>),
82 Predicate(Spanned<BoolExpr>),
83 }
84
85 #[derive(Debug, Clone)]
86 pub enum ExtractExpr {
87 Ident(Spanned<Ident>),
88 #[expect(dead_code, reason = "unused spanned")]
89 Underscore(#[rust_sitter::leaf(text = "_")] Spanned<()>),
90 Flatten(#[rust_sitter::leaf(text = "*")] (), Box<ExtractExpr>),
91 Untuple(
92 #[rust_sitter::leaf(text = "(")] (),
93 #[rust_sitter::delimited(
94 #[rust_sitter::leaf(text = ",")]
95 ()
96 )]
97 Vec<Spanned<ExtractExpr>>,
98 #[rust_sitter::leaf(text = ")")] (),
99 ),
100 }
101
102 #[derive(Debug, Clone)]
103 pub struct InputRelationExpr {
104 pub name: Spanned<Ident>,
105
106 #[rust_sitter::leaf(text = "(")]
107 _l_paren: (),
108
109 #[rust_sitter::delimited(
110 #[rust_sitter::leaf(text = ",")]
111 ()
112 )]
113 pub fields: Vec<Spanned<ExtractExpr>>,
114
115 #[rust_sitter::leaf(text = ")")]
116 _r_paren: (),
117 }
118
119 #[derive(Debug, Clone)]
120 pub struct TargetRelationExpr {
121 pub name: Spanned<Ident>,
122
123 pub at_node: Option<AtNode>,
124
125 #[rust_sitter::leaf(text = "(")]
126 _l_paren: (),
127
128 #[rust_sitter::delimited(
129 #[rust_sitter::leaf(text = ",")]
130 ()
131 )]
132 pub fields: Vec<Spanned<TargetExpr>>,
133
134 #[rust_sitter::leaf(text = ")")]
135 _r_paren: (),
136 }
137
138 #[derive(Debug, Clone)]
139 pub struct AtNode {
140 #[rust_sitter::leaf(text = "@")]
141 _at: (),
142
143 pub node: Spanned<TargetExpr>,
144 }
145
146 #[derive(Debug, Clone)]
147 pub enum TargetExpr {
148 Expr(IntExpr),
149 Aggregation(Aggregation),
150 Index(
151 #[rust_sitter::leaf(text = "index")] (),
152 #[rust_sitter::leaf(text = "(")] (),
153 #[rust_sitter::leaf(text = ")")] (),
154 ),
155 }
156
157 impl TargetExpr {
158 pub fn idents(&self) -> Vec<&Ident> {
159 match self {
160 TargetExpr::Expr(e) => e.idents(),
161 TargetExpr::Aggregation(Aggregation::Count(_)) => vec![],
162 TargetExpr::Aggregation(
163 Aggregation::CountUnique(_, _, idents, _)
164 | Aggregation::CollectVec(_, _, idents, _),
165 ) => idents.iter().map(|i| &i.value).collect(),
166 TargetExpr::Aggregation(
167 Aggregation::Min(_, _, a, _)
168 | Aggregation::Max(_, _, a, _)
169 | Aggregation::Sum(_, _, a, _)
170 | Aggregation::Choose(_, _, a, _),
171 ) => vec![a],
172 TargetExpr::Index(_, _, _) => vec![],
173 }
174 }
175 }
176
177 #[derive(Debug, Clone)]
178 pub enum Aggregation {
179 Min(
180 #[rust_sitter::leaf(text = "min")] (),
181 #[rust_sitter::leaf(text = "(")] (),
182 Spanned<Ident>,
183 #[rust_sitter::leaf(text = ")")] (),
184 ),
185 Max(
186 #[rust_sitter::leaf(text = "max")] (),
187 #[rust_sitter::leaf(text = "(")] (),
188 Spanned<Ident>,
189 #[rust_sitter::leaf(text = ")")] (),
190 ),
191 Sum(
192 #[rust_sitter::leaf(text = "sum")] (),
193 #[rust_sitter::leaf(text = "(")] (),
194 Spanned<Ident>,
195 #[rust_sitter::leaf(text = ")")] (),
196 ),
197 Count(#[rust_sitter::leaf(text = "count(*)")] ()),
198 CountUnique(
199 #[rust_sitter::leaf(text = "count")] (),
200 #[rust_sitter::leaf(text = "(")] (),
201 #[rust_sitter::delimited(
202 #[rust_sitter::leaf(text = ",")]
203 ()
204 )]
205 Vec<Spanned<Ident>>,
206 #[rust_sitter::leaf(text = ")")] (),
207 ),
208 Choose(
209 #[rust_sitter::leaf(text = "choose")] (),
210 #[rust_sitter::leaf(text = "(")] (),
211 Spanned<Ident>,
212 #[rust_sitter::leaf(text = ")")] (),
213 ),
214 CollectVec(
215 #[rust_sitter::leaf(text = "collect_vec")] (),
216 #[rust_sitter::leaf(text = "(")] (),
217 #[rust_sitter::delimited(
218 #[rust_sitter::leaf(text = ",")]
219 ()
220 )]
221 Vec<Spanned<Ident>>,
222 #[rust_sitter::leaf(text = ")")] (),
223 ),
224 }
225
226 #[derive(Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Debug)]
227 pub struct Ident {
228 #[rust_sitter::leaf(pattern = r"[a-zA-Z][a-zA-Z0-9_]*", transform = |s| s.to_string())]
229 pub name: String,
230 }
231
232 #[rust_sitter::extra]
233 struct Whitespace {
234 #[rust_sitter::leaf(pattern = r"\s")]
235 _whitespace: (),
236 }
237
238 #[rust_sitter::extra]
239 struct Comment {
240 #[rust_sitter::leaf(pattern = r"(#|\/\/).*")]
241 _comment: (),
242 }
243
244 #[derive(Debug, Clone)]
245 pub enum BoolOp {
246 Lt(#[rust_sitter::leaf(text = "<")] ()),
247 LtEq(#[rust_sitter::leaf(text = "<=")] ()),
248 Gt(#[rust_sitter::leaf(text = ">")] ()),
249 GtEq(#[rust_sitter::leaf(text = ">=")] ()),
250 Eq(#[rust_sitter::leaf(text = "==")] ()),
251 Neq(#[rust_sitter::leaf(text = "!=")] ()),
252 }
253
254 #[derive(Debug, Clone)]
255 pub struct BoolExpr {
256 #[rust_sitter::leaf(text = "(")]
257 _l_brace: (),
258
259 pub left: Spanned<IntExpr>,
260 pub op: BoolOp,
261 pub right: Spanned<IntExpr>,
262
263 #[rust_sitter::leaf(text = ")")]
264 _r_brace: (),
265 }
266
267 #[derive(Debug, Clone)]
268 pub enum IntExpr {
269 Ident(Spanned<Ident>),
270 Integer(
271 #[rust_sitter::leaf(pattern = r"[0-9]+", transform = |s| s.parse().unwrap())]
272 Spanned<i64>,
273 ),
274 Parenthesized(
275 #[rust_sitter::leaf(text = "(")] (),
276 Box<IntExpr>,
277 #[rust_sitter::leaf(text = ")")] (),
278 ),
279 #[rust_sitter::prec_left(1)]
280 Add(
281 Box<IntExpr>,
282 #[rust_sitter::leaf(text = "+")] (),
283 Box<IntExpr>,
284 ),
285 #[rust_sitter::prec_left(1)]
286 Sub(
287 Box<IntExpr>,
288 #[rust_sitter::leaf(text = "-")] (),
289 Box<IntExpr>,
290 ),
291 #[rust_sitter::prec_left(2)]
292 Mul(
293 Box<IntExpr>,
294 #[rust_sitter::leaf(text = "*")] (),
295 Box<IntExpr>,
296 ),
297 #[rust_sitter::prec_left(1)]
298 Mod(
299 Box<IntExpr>,
300 #[rust_sitter::leaf(text = "%")] (),
301 Box<IntExpr>,
302 ),
303 }
304
305 impl IntExpr {
306 pub fn idents(&self) -> Vec<&Ident> {
307 match self {
308 IntExpr::Ident(i) => vec![i],
309 IntExpr::Integer(_) => vec![],
310 IntExpr::Parenthesized(_, e, _) => e.idents(),
311 IntExpr::Add(l, _, r) => {
312 let mut idents = l.idents();
313 idents.extend(r.idents());
314 idents
315 }
316 IntExpr::Sub(l, _, r) => {
317 let mut idents = l.idents();
318 idents.extend(r.idents());
319 idents
320 }
321 IntExpr::Mul(l, _, r) => {
322 let mut idents = l.idents();
323 idents.extend(r.idents());
324 idents
325 }
326 IntExpr::Mod(l, _, r) => {
327 let mut idents = l.idents();
328 idents.extend(r.idents());
329 idents
330 }
331 }
332 }
333 }
334}