sentri_dsl_parser/
grammar.rs1#![allow(missing_docs)]
3
4use pest_derive::Parser;
5
6#[allow(non_camel_case_types)]
8#[derive(Parser)]
9#[grammar_inline = r#"
10WHITESPACE = _{ " " | "\t" | NEWLINE }
11NEWLINE = @{ "\r\n" | "\n" }
12
13// Identifiers and literals
14identifier = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* }
15layer_name = @{ "bundler" | "account" | "paymaster" | "protocol" | "entrypoint" }
16integer = @{ "-"? ~ ASCII_DIGIT+ }
17
18// Operators (ordered by precedence)
19eq = { "==" }
20neq = { "!=" }
21lt = { "<" }
22gt = { ">" }
23lte = { "<=" }
24gte = { ">=" }
25and = { "&&" }
26or = { "||" }
27not = { "!" }
28
29// Literals
30boolean = @{ "true" | "false" }
31
32// Qualified identifiers with optional layer scope (layer::identifier)
33qualified_id = { layer_name ~ "::" ~ identifier }
34simple_id = { identifier }
35var_id = { qualified_id | simple_id }
36
37// Function call - must be tried before identifier
38function_call = { identifier ~ "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" }
39
40// Atoms: function calls, literals, or identifiers (in order of specificity)
41atom = _{ function_call | boolean | integer | var_id }
42
43// Primary expressions with parentheses
44primary = { "(" ~ expr ~ ")" | atom }
45
46// Unary operators
47unary = { not* ~ primary }
48
49// Comparison operators
50comparison = { unary ~ ((eq | neq | lte | gte | lt | gt) ~ unary)* }
51
52// Logical AND
53logical_and = { comparison ~ (and ~ comparison)* }
54
55// Logical OR
56logical_or = { logical_and ~ (or ~ logical_and)* }
57
58// Main expression
59expr = { logical_or }
60
61// Top-level invariant
62invariant_def = {
63 "invariant" ~ identifier ~ ("(" ~ layer_name ~ ("," ~ layer_name)* ~ ")")? ~ "{" ~ expr ~ "}"
64}
65
66file = { SOI ~ invariant_def+ ~ EOI }
67"#]
68pub struct SentriGrammar;
69
70pub use SentriGrammar as Grammar;