cedar_policy_core/parser/cst.rs
1/*
2 * Copyright Cedar Contributors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use smol_str::SmolStr;
18
19// shortcut because we need CST nodes to potentially be empty,
20// for example, if part of it failed the parse, we can
21// still recover other parts
22type Node<N> = super::node::Node<Option<N>>;
23
24/// The set of policy statements that forms a policy set
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct Policies(pub Vec<Node<Policy>>);
27
28/// Annotations: application-defined data, as a key-value pair
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Annotation {
31 /// key
32 pub key: Node<Ident>,
33 /// value
34 pub value: Option<Node<Str>>,
35}
36
37/// Literal strings
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum Str {
40 /// regular quoted string
41 String(SmolStr),
42 // this is not generated by the parser at time of comment,
43 // but left as future improvement and to clarify the
44 // validity of the above `String` form
45 /// poorly formed string
46 #[allow(unused)]
47 Invalid(SmolStr),
48}
49
50/// Policy statement, the main building block of the language
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct Policy {
53 /// Annotations
54 pub annotations: Vec<Node<Annotation>>,
55 /// policy effect
56 pub effect: Node<Ident>,
57 /// Variables
58 pub variables: Vec<Node<VariableDef>>,
59 /// Conditions
60 pub conds: Vec<Node<Cond>>,
61}
62
63/// The variable part of one of the main item of a policy
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct VariableDef {
66 /// identifier, expected:
67 /// principal, action, resource
68 pub variable: Node<Ident>,
69 /// type of entity using previously considered `var : type` syntax. This is
70 /// not used for anything other than error reporting.
71 pub unused_type_name: Option<Node<Name>>,
72 /// type of entity using current `var is type` syntax
73 pub entity_type: Option<Node<Add>>,
74 /// hierarchy of entity
75 pub ineq: Option<(RelOp, Node<Expr>)>,
76}
77
78/// Any identifier, including special ones
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80#[allow(unused)] // definitional, or for later improvements
81pub enum Ident {
82 // Variables
83 /// principal
84 Principal,
85 /// action
86 Action,
87 /// resource
88 Resource,
89 /// context
90 Context,
91
92 // Other Identifiers
93 /// true
94 True,
95 /// false
96 False,
97 /// permit
98 Permit,
99 /// forbid
100 Forbid,
101 /// when
102 When,
103 /// unless
104 Unless,
105 /// in
106 In,
107 /// has
108 Has,
109 /// like
110 Like,
111 /// is
112 Is,
113 /// if
114 If,
115 /// then
116 Then,
117 /// else
118 Else,
119
120 // Regular identifiers
121 /// user-supplied, in the proper form
122 Ident(SmolStr),
123 // This is not generated from the parser a time of comment,
124 // but here for future improvement and to clarify
125 // the validity of the above `Ident` form
126 /// user-supplied, not in the proper form
127 Invalid(String),
128}
129
130/// Conditions: powerful extensions to a policy
131#[derive(Debug, Clone, PartialEq, Eq)]
132pub struct Cond {
133 /// initial ident, expected to be "when" or "unless"
134 pub cond: Node<Ident>,
135 /// related expression. expected to not be `None`, but if it's `None`, that
136 /// indicates the body was empty (as in `when {}`), and we can report a good
137 /// error message
138 pub expr: Option<Node<Expr>>,
139}
140
141/// The main computation aspect of a policy, outer
142#[derive(Debug, Clone, PartialEq, Eq)]
143pub struct Expr {
144 /// expression content
145 pub expr: Box<ExprData>,
146}
147/// The main computation aspect of a policy, inner
148#[derive(Debug, Clone, PartialEq, Eq)]
149pub enum ExprData {
150 /// || Op
151 Or(Node<Or>),
152 /// if-then-else
153 If(Node<Expr>, Node<Expr>, Node<Expr>),
154}
155/// Logical Or
156#[derive(Debug, Clone, PartialEq, Eq)]
157pub struct Or {
158 /// a singleton is a wrapper for a higher-priority node
159 pub initial: Node<And>,
160 /// additional elements represent a chained `||` computation
161 pub extended: Vec<Node<And>>,
162}
163/// Logical And
164#[derive(Debug, Clone, PartialEq, Eq)]
165pub struct And {
166 /// a singleton is a wrapper for a higher-priority node
167 pub initial: Node<Relation>,
168 /// additional elements represent a chained `&&` computation
169 pub extended: Vec<Node<Relation>>,
170}
171/// Comparison relations
172#[derive(Debug, Clone, PartialEq, Eq)]
173pub enum Relation {
174 /// Regular relations
175 Common {
176 /// a singleton is a wrapper for a higher-priority node
177 initial: Node<Add>,
178 /// additional elements represent chained `>`, `<`, etc. computation
179 extended: Vec<(RelOp, Node<Add>)>,
180 },
181 /// Built-in 'has' operation
182 Has {
183 /// element that may have a field
184 target: Node<Add>,
185 /// a field the element may have
186 field: Node<Add>,
187 },
188 /// Built-in 'like' operation
189 Like {
190 /// element to test
191 target: Node<Add>,
192 /// pattern to match on
193 pattern: Node<Add>,
194 },
195 /// Built-in '.. is .. (in ..)?' operation
196 IsIn {
197 /// element that may be an entity type and `in` an entity
198 target: Node<Add>,
199 /// entity type to check for
200 entity_type: Node<Add>,
201 /// entity that the target may be `in`
202 in_entity: Option<Node<Add>>,
203 },
204}
205
206/// The operation involved in a comparision
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum RelOp {
209 /// <
210 Less,
211 /// <=
212 LessEq,
213 /// >=
214 GreaterEq,
215 /// >
216 Greater,
217 /// !=
218 NotEq,
219 /// ==
220 Eq,
221 /// in
222 In,
223 /// =
224 ///
225 /// This is always invalid, but included so we can give a nice error suggesting '==' instead
226 InvalidSingleEq,
227}
228
229/// Allowed Ops for Add
230#[derive(Debug, Clone, Copy, PartialEq, Eq)]
231pub enum AddOp {
232 /// +
233 Plus,
234 /// -
235 Minus,
236}
237
238/// Allowed Ops for Mult
239#[derive(Debug, Clone, Copy, PartialEq, Eq)]
240pub enum MultOp {
241 /// *
242 Times,
243 /// /
244 Divide,
245 /// %
246 Mod,
247}
248
249/// Allowed Ops for Neg
250#[derive(Debug, Clone, Copy, PartialEq, Eq)]
251pub enum NegOp {
252 /// count of `!`'s
253 Bang(u8),
254 /// too many `!`'s
255 OverBang,
256 /// count of `-`'s
257 Dash(u8),
258 /// too many `-`'s
259 OverDash,
260}
261
262/// Additive arithmetic
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub struct Add {
265 /// a singleton is a wrapper for a higher-priority node
266 pub initial: Node<Mult>,
267 /// additional elements represent a chained `+`, `-`, etc. computation
268 pub extended: Vec<(AddOp, Node<Mult>)>,
269}
270/// Multiplicative arithmetic
271#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct Mult {
273 /// a singleton is a wrapper for a higher-priority node
274 pub initial: Node<Unary>,
275 /// additional elements represent a chained `*`, `/`, etc. computation
276 pub extended: Vec<(MultOp, Node<Unary>)>,
277}
278/// Unary negations
279#[derive(Debug, Clone, PartialEq, Eq)]
280pub struct Unary {
281 /// the negation operation, if any
282 pub op: Option<NegOp>,
283 /// higher-priority node the negation is applied to
284 pub item: Node<Member>,
285}
286/// Members on a primary item, accessed with '.'
287#[derive(Debug, Clone, PartialEq, Eq)]
288pub struct Member {
289 /// Main element
290 pub item: Node<Primary>,
291 /// fields, indexes, etc.
292 pub access: Vec<Node<MemAccess>>,
293}
294/// Forms of members and their accessors
295#[derive(Debug, Clone, PartialEq, Eq)]
296pub enum MemAccess {
297 /// field identifier
298 Field(Node<Ident>),
299 /// function call
300 Call(Vec<Node<Expr>>),
301 /// index of a member
302 Index(Node<Expr>),
303}
304/// Low-level elements like literals
305#[derive(Debug, Clone, PartialEq, Eq)]
306pub enum Primary {
307 /// Literal
308 Literal(Node<Literal>),
309 /// References to entities
310 Ref(Node<Ref>),
311 /// Constructed elements with names
312 Name(Node<Name>),
313 /// Template Slots
314 Slot(Node<Slot>),
315 /// Parentheses
316 Expr(Node<Expr>),
317 /// Constructed array
318 EList(Vec<Node<Expr>>),
319 /// Constructed record
320 RInits(Vec<Node<RecInit>>),
321}
322
323/// UID and Type of named items
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct Name {
326 /// path, like: "name0::name1::name"
327 pub path: Vec<Node<Ident>>,
328 /// Singleton name
329 pub name: Node<Ident>,
330}
331/// Reference to an entity
332#[derive(Debug, Clone, PartialEq, Eq)]
333pub enum Ref {
334 /// UID
335 Uid {
336 /// The path/type of an entity
337 path: Node<Name>,
338 /// EID, quoted name
339 eid: Node<Str>,
340 },
341 /// Lookup references
342 Ref {
343 /// The path/type of an entity
344 path: Node<Name>,
345 /// The indicated fields of the entity
346 rinits: Vec<Node<RefInit>>,
347 },
348}
349/// Elements in a ref: `field: data`
350#[derive(Debug, Clone, PartialEq, Eq)]
351pub struct RefInit(pub Node<Ident>, pub Node<Literal>);
352/// Elements of records: `field_from_expr: data_from_expr`
353#[derive(Debug, Clone, PartialEq, Eq)]
354pub struct RecInit(pub Node<Expr>, pub Node<Expr>);
355
356/// Raw values
357#[derive(Debug, Clone, PartialEq, Eq)]
358pub enum Literal {
359 /// true
360 True,
361 /// false
362 False,
363 /// some integer
364 Num(u64),
365 /// some String
366 Str(Node<Str>),
367}
368
369/// Template Slots
370#[derive(Debug, Clone, PartialEq, Eq)]
371pub enum Slot {
372 /// Slot for Principal Constraints
373 Principal,
374 /// Slot for Resource Constraints
375 Resource,
376 /// Slot other than one of the valid slots
377 Other(SmolStr),
378}
379
380impl Slot {
381 /// Check if a slot matches a scope variable.
382 pub fn matches(&self, var: crate::ast::Var) -> bool {
383 matches!(
384 (self, var),
385 (Slot::Principal, crate::ast::Var::Principal)
386 | (Slot::Resource, crate::ast::Var::Resource)
387 )
388 }
389}