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}