cedar_policy_core/est/
expr.rs

1/*
2 * Copyright 2022-2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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 super::utils::unwrap_or_clone;
18use super::EstToAstError;
19use crate::ast;
20use crate::entities::{JSONValue, JsonDeserializationError, TypeAndId};
21use crate::parser::cst;
22use crate::parser::err::{ParseError, ParseErrors};
23use crate::parser::unescape;
24use crate::parser::ASTNode;
25use either::Either;
26use serde::{Deserialize, Serialize};
27use smol_str::SmolStr;
28use std::collections::HashMap;
29use std::sync::Arc;
30
31/// Serde JSON structure for a Cedar expression in the EST format
32#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
33#[serde(untagged)]
34pub enum Expr {
35    /// Any Cedar expression other than an extension function call.
36    /// We try to match this first, see docs on #[serde(untagged)].
37    ExprNoExt(ExprNoExt),
38    /// If that didn't match (because the key is not one of the keys defined in
39    /// `ExprNoExt`), we assume we have an extension function call, where the
40    /// key is the name of an extension function or method.
41    ExtFuncCall(ExtFuncCall),
42}
43
44/// Serde JSON structure for [any Cedar expression other than an extension
45/// function call] in the EST format
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47#[serde(deny_unknown_fields)]
48pub enum ExprNoExt {
49    /// Literal value (including anything that's legal to express in the
50    /// attribute-value JSON format)
51    Value(JSONValue),
52    /// Var
53    Var(ast::Var),
54    /// Template slot
55    Slot(ast::SlotId),
56    /// Unknown (for partial evaluation)
57    Unknown {
58        /// Name of the unknown
59        name: SmolStr,
60    },
61    /// `!`
62    #[serde(rename = "!")]
63    Not {
64        /// Argument
65        arg: Arc<Expr>,
66    },
67    /// `-`
68    #[serde(rename = "neg")]
69    Neg {
70        /// Argument
71        arg: Arc<Expr>,
72    },
73    /// `==`
74    #[serde(rename = "==")]
75    Eq {
76        /// Left-hand argument
77        left: Arc<Expr>,
78        /// Right-hand argument
79        right: Arc<Expr>,
80    },
81    /// `!=`
82    #[serde(rename = "!=")]
83    NotEq {
84        /// Left-hand argument
85        left: Arc<Expr>,
86        /// Right-hand argument
87        right: Arc<Expr>,
88    },
89    /// `in`
90    #[serde(rename = "in")]
91    In {
92        /// Left-hand argument
93        left: Arc<Expr>,
94        /// Right-hand argument
95        right: Arc<Expr>,
96    },
97    /// `<`
98    #[serde(rename = "<")]
99    Less {
100        /// Left-hand argument
101        left: Arc<Expr>,
102        /// Right-hand argument
103        right: Arc<Expr>,
104    },
105    /// `<=`
106    #[serde(rename = "<=")]
107    LessEq {
108        /// Left-hand argument
109        left: Arc<Expr>,
110        /// Right-hand argument
111        right: Arc<Expr>,
112    },
113    /// `>`
114    #[serde(rename = ">")]
115    Greater {
116        /// Left-hand argument
117        left: Arc<Expr>,
118        /// Right-hand argument
119        right: Arc<Expr>,
120    },
121    /// `>=`
122    #[serde(rename = ">=")]
123    GreaterEq {
124        /// Left-hand argument
125        left: Arc<Expr>,
126        /// Right-hand argument
127        right: Arc<Expr>,
128    },
129    /// `&&`
130    #[serde(rename = "&&")]
131    And {
132        /// Left-hand argument
133        left: Arc<Expr>,
134        /// Right-hand argument
135        right: Arc<Expr>,
136    },
137    /// `||`
138    #[serde(rename = "||")]
139    Or {
140        /// Left-hand argument
141        left: Arc<Expr>,
142        /// Right-hand argument
143        right: Arc<Expr>,
144    },
145    /// `+`
146    #[serde(rename = "+")]
147    Add {
148        /// Left-hand argument
149        left: Arc<Expr>,
150        /// Right-hand argument
151        right: Arc<Expr>,
152    },
153    /// `-`
154    #[serde(rename = "-")]
155    Sub {
156        /// Left-hand argument
157        left: Arc<Expr>,
158        /// Right-hand argument
159        right: Arc<Expr>,
160    },
161    /// `*`
162    #[serde(rename = "*")]
163    Mul {
164        /// Left-hand argument
165        left: Arc<Expr>,
166        /// Right-hand argument
167        right: Arc<Expr>,
168    },
169    /// `contains()`
170    #[serde(rename = "contains")]
171    Contains {
172        /// Left-hand argument (receiver)
173        left: Arc<Expr>,
174        /// Right-hand argument (inside the `()`)
175        right: Arc<Expr>,
176    },
177    /// `containsAll()`
178    #[serde(rename = "containsAll")]
179    ContainsAll {
180        /// Left-hand argument (receiver)
181        left: Arc<Expr>,
182        /// Right-hand argument (inside the `()`)
183        right: Arc<Expr>,
184    },
185    /// `containsAny()`
186    #[serde(rename = "containsAny")]
187    ContainsAny {
188        /// Left-hand argument (receiver)
189        left: Arc<Expr>,
190        /// Right-hand argument (inside the `()`)
191        right: Arc<Expr>,
192    },
193    /// Get-attribute
194    #[serde(rename = ".")]
195    GetAttr {
196        /// Left-hand argument
197        left: Arc<Expr>,
198        /// Attribute name
199        attr: SmolStr,
200    },
201    /// `has`
202    #[serde(rename = "has")]
203    HasAttr {
204        /// Left-hand argument
205        left: Arc<Expr>,
206        /// Attribute name
207        attr: SmolStr,
208    },
209    /// `like`
210    #[serde(rename = "like")]
211    Like {
212        /// Left-hand argument
213        left: Arc<Expr>,
214        /// Pattern
215        pattern: SmolStr,
216    },
217    /// Ternary
218    #[serde(rename = "if-then-else")]
219    If {
220        /// Condition
221        #[serde(rename = "if")]
222        cond_expr: Arc<Expr>,
223        /// `then` expression
224        #[serde(rename = "then")]
225        then_expr: Arc<Expr>,
226        /// `else` expression
227        #[serde(rename = "else")]
228        else_expr: Arc<Expr>,
229    },
230    /// Set literal, whose elements may be arbitrary expressions
231    /// (which is why we need this case specifically and can't just
232    /// use Expr::Value)
233    Set(Vec<Expr>),
234    /// Record literal, whose elements may be arbitrary expressions
235    /// (which is why we need this case specifically and can't just
236    /// use Expr::Value)
237    Record(HashMap<SmolStr, Expr>),
238}
239
240/// Serde JSON structure for an extension function call in the EST format
241#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
242pub struct ExtFuncCall {
243    /// maps the name of the function to a JSON list/array of the arguments.
244    /// Note that for method calls, the method receiver is the first argument.
245    /// For example, for `a.isInRange(b)`, the first argument is `a` and the
246    /// second argument is `b`.
247    ///
248    /// This map should only ever have one k-v pair, but we make it a map in
249    /// order to get the correct JSON structure we want.
250    #[serde(flatten)]
251    call: HashMap<SmolStr, Vec<Expr>>,
252}
253
254#[allow(clippy::should_implement_trait)] // the names of arithmetic constructors alias with those of certain trait methods such as `add` of `std::ops::Add`
255impl Expr {
256    /// literal
257    pub fn lit(lit: JSONValue) -> Self {
258        Expr::ExprNoExt(ExprNoExt::Value(lit))
259    }
260
261    /// principal, action, resource, context
262    pub fn var(var: ast::Var) -> Self {
263        Expr::ExprNoExt(ExprNoExt::Var(var))
264    }
265
266    /// Template slots
267    pub fn slot(slot: ast::SlotId) -> Self {
268        Expr::ExprNoExt(ExprNoExt::Slot(slot))
269    }
270
271    /// Partial-evaluation unknowns
272    pub fn unknown(name: impl Into<SmolStr>) -> Self {
273        Expr::ExprNoExt(ExprNoExt::Unknown { name: name.into() })
274    }
275
276    /// `!`
277    pub fn not(e: Expr) -> Self {
278        Expr::ExprNoExt(ExprNoExt::Not { arg: Arc::new(e) })
279    }
280
281    /// `-`
282    pub fn neg(e: Expr) -> Self {
283        Expr::ExprNoExt(ExprNoExt::Neg { arg: Arc::new(e) })
284    }
285
286    /// `==`
287    pub fn eq(left: Expr, right: Expr) -> Self {
288        Expr::ExprNoExt(ExprNoExt::Eq {
289            left: Arc::new(left),
290            right: Arc::new(right),
291        })
292    }
293
294    /// `!=`
295    pub fn noteq(left: Expr, right: Expr) -> Self {
296        Expr::ExprNoExt(ExprNoExt::NotEq {
297            left: Arc::new(left),
298            right: Arc::new(right),
299        })
300    }
301
302    /// `in`
303    pub fn _in(left: Expr, right: Expr) -> Self {
304        Expr::ExprNoExt(ExprNoExt::In {
305            left: Arc::new(left),
306            right: Arc::new(right),
307        })
308    }
309
310    /// `<`
311    pub fn less(left: Expr, right: Expr) -> Self {
312        Expr::ExprNoExt(ExprNoExt::Less {
313            left: Arc::new(left),
314            right: Arc::new(right),
315        })
316    }
317
318    /// `<=`
319    pub fn lesseq(left: Expr, right: Expr) -> Self {
320        Expr::ExprNoExt(ExprNoExt::LessEq {
321            left: Arc::new(left),
322            right: Arc::new(right),
323        })
324    }
325
326    /// `>`
327    pub fn greater(left: Expr, right: Expr) -> Self {
328        Expr::ExprNoExt(ExprNoExt::Greater {
329            left: Arc::new(left),
330            right: Arc::new(right),
331        })
332    }
333
334    /// `>=`
335    pub fn greatereq(left: Expr, right: Expr) -> Self {
336        Expr::ExprNoExt(ExprNoExt::GreaterEq {
337            left: Arc::new(left),
338            right: Arc::new(right),
339        })
340    }
341
342    /// `&&`
343    pub fn and(left: Expr, right: Expr) -> Self {
344        Expr::ExprNoExt(ExprNoExt::And {
345            left: Arc::new(left),
346            right: Arc::new(right),
347        })
348    }
349
350    /// `||`
351    pub fn or(left: Expr, right: Expr) -> Self {
352        Expr::ExprNoExt(ExprNoExt::Or {
353            left: Arc::new(left),
354            right: Arc::new(right),
355        })
356    }
357
358    /// `+`
359    pub fn add(left: Expr, right: Expr) -> Self {
360        Expr::ExprNoExt(ExprNoExt::Add {
361            left: Arc::new(left),
362            right: Arc::new(right),
363        })
364    }
365
366    /// `-`
367    pub fn sub(left: Expr, right: Expr) -> Self {
368        Expr::ExprNoExt(ExprNoExt::Sub {
369            left: Arc::new(left),
370            right: Arc::new(right),
371        })
372    }
373
374    /// `*`
375    pub fn mul(left: Expr, right: Expr) -> Self {
376        Expr::ExprNoExt(ExprNoExt::Mul {
377            left: Arc::new(left),
378            right: Arc::new(right),
379        })
380    }
381
382    /// `left.contains(right)`
383    pub fn contains(left: Arc<Expr>, right: Expr) -> Self {
384        Expr::ExprNoExt(ExprNoExt::Contains {
385            left,
386            right: Arc::new(right),
387        })
388    }
389
390    /// `left.containsAll(right)`
391    pub fn contains_all(left: Arc<Expr>, right: Expr) -> Self {
392        Expr::ExprNoExt(ExprNoExt::ContainsAll {
393            left,
394            right: Arc::new(right),
395        })
396    }
397
398    /// `left.containsAny(right)`
399    pub fn contains_any(left: Arc<Expr>, right: Expr) -> Self {
400        Expr::ExprNoExt(ExprNoExt::ContainsAny {
401            left,
402            right: Arc::new(right),
403        })
404    }
405
406    /// `left.attr`
407    pub fn get_attr(left: Expr, attr: SmolStr) -> Self {
408        Expr::ExprNoExt(ExprNoExt::GetAttr {
409            left: Arc::new(left),
410            attr,
411        })
412    }
413
414    /// `left has attr`
415    pub fn has_attr(left: Expr, attr: SmolStr) -> Self {
416        Expr::ExprNoExt(ExprNoExt::HasAttr {
417            left: Arc::new(left),
418            attr,
419        })
420    }
421
422    /// `left like pattern`
423    pub fn like(left: Expr, pattern: SmolStr) -> Self {
424        Expr::ExprNoExt(ExprNoExt::Like {
425            left: Arc::new(left),
426            pattern,
427        })
428    }
429
430    /// `if cond_expr then then_expr else else_expr`
431    pub fn ite(cond_expr: Expr, then_expr: Expr, else_expr: Expr) -> Self {
432        Expr::ExprNoExt(ExprNoExt::If {
433            cond_expr: Arc::new(cond_expr),
434            then_expr: Arc::new(then_expr),
435            else_expr: Arc::new(else_expr),
436        })
437    }
438
439    /// e.g. [1+2, !(context has department)]
440    pub fn set(elements: Vec<Expr>) -> Self {
441        Expr::ExprNoExt(ExprNoExt::Set(elements))
442    }
443
444    /// e.g. {foo: 1+2, bar: !(context has department)}
445    pub fn record(map: HashMap<SmolStr, Expr>) -> Self {
446        Expr::ExprNoExt(ExprNoExt::Record(map))
447    }
448
449    /// extension function call, including method calls
450    pub fn ext_call(fn_name: SmolStr, args: Vec<Expr>) -> Self {
451        Expr::ExtFuncCall(ExtFuncCall {
452            call: [(fn_name, args)].into_iter().collect(),
453        })
454    }
455
456    /// Consume the `Expr`, producing a string literal if it was a string literal, otherwise `None`
457    pub fn into_string_literal(self) -> Option<SmolStr> {
458        match self {
459            Expr::ExprNoExt(ExprNoExt::Value(JSONValue::String(s))) => Some(s),
460            _ => None,
461        }
462    }
463}
464
465impl TryFrom<Expr> for ast::Expr {
466    type Error = EstToAstError;
467    fn try_from(expr: Expr) -> Result<ast::Expr, EstToAstError> {
468        match expr {
469            Expr::ExprNoExt(ExprNoExt::Value(jsonvalue)) => {
470                jsonvalue.into_expr().map(Into::into).map_err(Into::into)
471            }
472            Expr::ExprNoExt(ExprNoExt::Var(var)) => Ok(ast::Expr::var(var)),
473            Expr::ExprNoExt(ExprNoExt::Slot(slot)) => Ok(ast::Expr::slot(slot)),
474            Expr::ExprNoExt(ExprNoExt::Unknown { name }) => Ok(ast::Expr::unknown(name)),
475            Expr::ExprNoExt(ExprNoExt::Not { arg }) => {
476                Ok(ast::Expr::not((*arg).clone().try_into()?))
477            }
478            Expr::ExprNoExt(ExprNoExt::Neg { arg }) => {
479                Ok(ast::Expr::neg((*arg).clone().try_into()?))
480            }
481            Expr::ExprNoExt(ExprNoExt::Eq { left, right }) => Ok(ast::Expr::is_eq(
482                (*left).clone().try_into()?,
483                (*right).clone().try_into()?,
484            )),
485            Expr::ExprNoExt(ExprNoExt::NotEq { left, right }) => Ok(ast::Expr::noteq(
486                (*left).clone().try_into()?,
487                (*right).clone().try_into()?,
488            )),
489            Expr::ExprNoExt(ExprNoExt::In { left, right }) => Ok(ast::Expr::is_in(
490                (*left).clone().try_into()?,
491                (*right).clone().try_into()?,
492            )),
493            Expr::ExprNoExt(ExprNoExt::Less { left, right }) => Ok(ast::Expr::less(
494                (*left).clone().try_into()?,
495                (*right).clone().try_into()?,
496            )),
497            Expr::ExprNoExt(ExprNoExt::LessEq { left, right }) => Ok(ast::Expr::lesseq(
498                (*left).clone().try_into()?,
499                (*right).clone().try_into()?,
500            )),
501            Expr::ExprNoExt(ExprNoExt::Greater { left, right }) => Ok(ast::Expr::greater(
502                (*left).clone().try_into()?,
503                (*right).clone().try_into()?,
504            )),
505            Expr::ExprNoExt(ExprNoExt::GreaterEq { left, right }) => Ok(ast::Expr::greatereq(
506                (*left).clone().try_into()?,
507                (*right).clone().try_into()?,
508            )),
509            Expr::ExprNoExt(ExprNoExt::And { left, right }) => Ok(ast::Expr::and(
510                (*left).clone().try_into()?,
511                (*right).clone().try_into()?,
512            )),
513            Expr::ExprNoExt(ExprNoExt::Or { left, right }) => Ok(ast::Expr::or(
514                (*left).clone().try_into()?,
515                (*right).clone().try_into()?,
516            )),
517            Expr::ExprNoExt(ExprNoExt::Add { left, right }) => Ok(ast::Expr::add(
518                (*left).clone().try_into()?,
519                (*right).clone().try_into()?,
520            )),
521            Expr::ExprNoExt(ExprNoExt::Sub { left, right }) => Ok(ast::Expr::sub(
522                (*left).clone().try_into()?,
523                (*right).clone().try_into()?,
524            )),
525            Expr::ExprNoExt(ExprNoExt::Mul { left, right }) => {
526                let left: ast::Expr = (*left).clone().try_into()?;
527                let right: ast::Expr = (*right).clone().try_into()?;
528                let left_c = match left.expr_kind() {
529                    ast::ExprKind::Lit(ast::Literal::Long(c)) => Some(c),
530                    _ => None,
531                };
532                let right_c = match right.expr_kind() {
533                    ast::ExprKind::Lit(ast::Literal::Long(c)) => Some(c),
534                    _ => None,
535                };
536                match (left_c, right_c) {
537                    (_, Some(c)) => Ok(ast::Expr::mul(left, *c)),
538                    (Some(c), _) => Ok(ast::Expr::mul(right, *c)),
539                    (None, None) => Err(EstToAstError::MultiplicationByNonConstant {
540                        arg1: left,
541                        arg2: right,
542                    })?,
543                }
544            }
545            Expr::ExprNoExt(ExprNoExt::Contains { left, right }) => Ok(ast::Expr::contains(
546                (*left).clone().try_into()?,
547                (*right).clone().try_into()?,
548            )),
549            Expr::ExprNoExt(ExprNoExt::ContainsAll { left, right }) => Ok(ast::Expr::contains_all(
550                (*left).clone().try_into()?,
551                (*right).clone().try_into()?,
552            )),
553            Expr::ExprNoExt(ExprNoExt::ContainsAny { left, right }) => Ok(ast::Expr::contains_any(
554                (*left).clone().try_into()?,
555                (*right).clone().try_into()?,
556            )),
557            Expr::ExprNoExt(ExprNoExt::GetAttr { left, attr }) => {
558                Ok(ast::Expr::get_attr((*left).clone().try_into()?, attr))
559            }
560            Expr::ExprNoExt(ExprNoExt::HasAttr { left, attr }) => {
561                Ok(ast::Expr::has_attr((*left).clone().try_into()?, attr))
562            }
563            Expr::ExprNoExt(ExprNoExt::Like { left, pattern }) => {
564                match unescape::to_pattern(&pattern) {
565                    Ok(pattern) => Ok(ast::Expr::like((*left).clone().try_into()?, pattern)),
566                    Err(errs) => Err(EstToAstError::UnescapeError(errs)),
567                }
568            }
569            Expr::ExprNoExt(ExprNoExt::If {
570                cond_expr,
571                then_expr,
572                else_expr,
573            }) => Ok(ast::Expr::ite(
574                (*cond_expr).clone().try_into()?,
575                (*then_expr).clone().try_into()?,
576                (*else_expr).clone().try_into()?,
577            )),
578            Expr::ExprNoExt(ExprNoExt::Set(elements)) => Ok(ast::Expr::set(
579                elements
580                    .into_iter()
581                    .map(|el| el.try_into())
582                    .collect::<Result<Vec<_>, EstToAstError>>()?,
583            )),
584            Expr::ExprNoExt(ExprNoExt::Record(map)) => Ok(ast::Expr::record(
585                map.into_iter()
586                    .map(|(k, v)| Ok((k, v.try_into()?)))
587                    .collect::<Result<HashMap<SmolStr, _>, EstToAstError>>()?,
588            )),
589            Expr::ExtFuncCall(ExtFuncCall { call }) => {
590                match call.len() {
591                    0 => Err(EstToAstError::MissingOperator),
592                    1 => {
593                        let (fn_name, args) = call
594                            .into_iter()
595                            .next()
596                            .expect("already checked that len was 1");
597                        let fn_name = fn_name.parse().map_err(|errs|
598                            JsonDeserializationError::ExtnParseError(ParseError::WithContext {
599                                context: format!("expected valid operator or extension function name; got {fn_name}"),
600                                errs,
601                            })
602                        )?;
603                        Ok(ast::Expr::call_extension_fn(
604                            fn_name,
605                            args.into_iter()
606                                .map(TryInto::try_into)
607                                .collect::<Result<_, _>>()?,
608                        ))
609                    }
610                    _ => Err(EstToAstError::MultipleOperators {
611                        ops: call.into_keys().collect(),
612                    }),
613                }
614            }
615        }
616    }
617}
618
619impl From<ast::Expr> for Expr {
620    fn from(expr: ast::Expr) -> Expr {
621        match expr.into_expr_kind() {
622            ast::ExprKind::Lit(lit) => lit.into(),
623            ast::ExprKind::Var(var) => var.into(),
624            ast::ExprKind::Slot(slot) => slot.into(),
625            ast::ExprKind::Unknown { name, .. } => Expr::unknown(name),
626            ast::ExprKind::If {
627                test_expr,
628                then_expr,
629                else_expr,
630            } => Expr::ite(
631                unwrap_or_clone(test_expr).into(),
632                unwrap_or_clone(then_expr).into(),
633                unwrap_or_clone(else_expr).into(),
634            ),
635            ast::ExprKind::And { left, right } => {
636                Expr::and(unwrap_or_clone(left).into(), unwrap_or_clone(right).into())
637            }
638            ast::ExprKind::Or { left, right } => {
639                Expr::or(unwrap_or_clone(left).into(), unwrap_or_clone(right).into())
640            }
641            ast::ExprKind::UnaryApp { op, arg } => {
642                let arg = unwrap_or_clone(arg).into();
643                match op {
644                    ast::UnaryOp::Not => Expr::not(arg),
645                    ast::UnaryOp::Neg => Expr::neg(arg),
646                }
647            }
648            ast::ExprKind::BinaryApp { op, arg1, arg2 } => {
649                let arg1 = unwrap_or_clone(arg1).into();
650                let arg2 = unwrap_or_clone(arg2).into();
651                match op {
652                    ast::BinaryOp::Eq => Expr::eq(arg1, arg2),
653                    ast::BinaryOp::In => Expr::_in(arg1, arg2),
654                    ast::BinaryOp::Less => Expr::less(arg1, arg2),
655                    ast::BinaryOp::LessEq => Expr::lesseq(arg1, arg2),
656                    ast::BinaryOp::Add => Expr::add(arg1, arg2),
657                    ast::BinaryOp::Sub => Expr::sub(arg1, arg2),
658                    ast::BinaryOp::Contains => Expr::contains(Arc::new(arg1), arg2),
659                    ast::BinaryOp::ContainsAll => Expr::contains_all(Arc::new(arg1), arg2),
660                    ast::BinaryOp::ContainsAny => Expr::contains_any(Arc::new(arg1), arg2),
661                }
662            }
663            ast::ExprKind::MulByConst { arg, constant } => Expr::mul(
664                unwrap_or_clone(arg).into(),
665                Expr::lit(JSONValue::Long(constant)),
666            ),
667            ast::ExprKind::ExtensionFunctionApp {
668                op: ast::ExtensionFunctionOp { function_name },
669                args,
670            } => {
671                let args = unwrap_or_clone(args).into_iter().map(Into::into).collect();
672                Expr::ext_call(function_name.to_string().into(), args)
673            }
674            ast::ExprKind::GetAttr { expr, attr } => {
675                Expr::get_attr(unwrap_or_clone(expr).into(), attr)
676            }
677            ast::ExprKind::HasAttr { expr, attr } => {
678                Expr::has_attr(unwrap_or_clone(expr).into(), attr)
679            }
680            ast::ExprKind::Like { expr, pattern } => {
681                Expr::like(unwrap_or_clone(expr).into(), pattern.to_string().into())
682            }
683            ast::ExprKind::Set(set) => {
684                Expr::set(unwrap_or_clone(set).into_iter().map(Into::into).collect())
685            }
686            ast::ExprKind::Record { pairs } => Expr::record(
687                unwrap_or_clone(pairs)
688                    .into_iter()
689                    .map(|(k, v)| (k, v.into()))
690                    .collect(),
691            ),
692        }
693    }
694}
695
696impl From<ast::Literal> for Expr {
697    fn from(lit: ast::Literal) -> Expr {
698        Expr::lit(JSONValue::from_lit(lit))
699    }
700}
701
702impl From<ast::Var> for Expr {
703    fn from(var: ast::Var) -> Expr {
704        Expr::var(var)
705    }
706}
707
708impl From<ast::SlotId> for Expr {
709    fn from(slot: ast::SlotId) -> Expr {
710        Expr::slot(slot)
711    }
712}
713
714impl TryFrom<cst::Expr> for Expr {
715    type Error = ParseErrors;
716    fn try_from(e: cst::Expr) -> Result<Expr, ParseErrors> {
717        match *e.expr {
718            cst::ExprData::Or(ASTNode { node, .. }) => match node {
719                Some(o) => o.try_into(),
720                None => Err(ParseError::ToAST("data should not be empty".to_string()).into()),
721            },
722            cst::ExprData::If(
723                ASTNode { node: if_node, .. },
724                ASTNode {
725                    node: then_node, ..
726                },
727                ASTNode {
728                    node: else_node, ..
729                },
730            ) => match (if_node, then_node, else_node) {
731                (Some(if_node), Some(then_node), Some(else_node)) => {
732                    let cond_expr = if_node.try_into()?;
733                    let then_expr = then_node.try_into()?;
734                    let else_expr = else_node.try_into()?;
735                    Ok(Expr::ite(cond_expr, then_expr, else_expr))
736                }
737                (_, _, _) => Err(ParseError::ToAST("data should not be empty".to_string()).into()),
738            },
739        }
740    }
741}
742
743impl TryFrom<cst::Or> for Expr {
744    type Error = ParseErrors;
745    fn try_from(o: cst::Or) -> Result<Expr, ParseErrors> {
746        let mut expr = match o.initial.node {
747            Some(a) => a.try_into(),
748            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
749        }?;
750        for node in o.extended {
751            let rhs = match node.node {
752                Some(a) => a.try_into(),
753                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
754            }?;
755            expr = Expr::or(expr, rhs);
756        }
757        Ok(expr)
758    }
759}
760
761impl TryFrom<cst::And> for Expr {
762    type Error = ParseErrors;
763    fn try_from(a: cst::And) -> Result<Expr, ParseErrors> {
764        let mut expr = match a.initial.node {
765            Some(r) => r.try_into(),
766            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
767        }?;
768        for node in a.extended {
769            let rhs = match node.node {
770                Some(r) => r.try_into(),
771                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
772            }?;
773            expr = Expr::and(expr, rhs);
774        }
775        Ok(expr)
776    }
777}
778
779impl TryFrom<cst::Relation> for Expr {
780    type Error = ParseErrors;
781    fn try_from(r: cst::Relation) -> Result<Expr, ParseErrors> {
782        match r {
783            cst::Relation::Common { initial, extended } => {
784                let mut expr = match initial.node {
785                    Some(a) => a.try_into(),
786                    None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
787                }?;
788                for (op, ASTNode { node, .. }) in extended {
789                    let rhs = match node {
790                        Some(a) => a.try_into(),
791                        None => {
792                            Err(ParseError::ToAST("node should not be empty".to_string()).into())
793                        }
794                    }?;
795                    match op {
796                        cst::RelOp::Eq => {
797                            expr = Expr::eq(expr, rhs);
798                        }
799                        cst::RelOp::NotEq => {
800                            expr = Expr::noteq(expr, rhs);
801                        }
802                        cst::RelOp::In => {
803                            expr = Expr::_in(expr, rhs);
804                        }
805                        cst::RelOp::Less => {
806                            expr = Expr::less(expr, rhs);
807                        }
808                        cst::RelOp::LessEq => {
809                            expr = Expr::lesseq(expr, rhs);
810                        }
811                        cst::RelOp::Greater => {
812                            expr = Expr::greater(expr, rhs);
813                        }
814                        cst::RelOp::GreaterEq => {
815                            expr = Expr::greatereq(expr, rhs);
816                        }
817                    }
818                }
819                Ok(expr)
820            }
821            cst::Relation::Has { target, field } => match (target, field) {
822                (
823                    ASTNode {
824                        node: Some(target), ..
825                    },
826                    ASTNode {
827                        node: Some(field), ..
828                    },
829                ) => {
830                    let target_expr = target.try_into()?;
831                    match Expr::try_from(field.clone()) {
832                        Ok(field_expr) => {
833                            let field_str = field_expr.into_string_literal().ok_or_else(|| {
834                                ParseError::ToAST(
835                                    "`has` RHS should be a string literal".to_string(),
836                                )
837                            })?;
838                            Ok(Expr::has_attr(target_expr, field_str))
839                        }
840                        Err(_) => match is_add_name(field) {
841                            Some(name) => Ok(Expr::has_attr(target_expr, name.to_string().into())),
842                            None => Err(ParseError::ToAST(
843                                "`has` RHS should be an attribute name or string literal"
844                                    .to_string(),
845                            )
846                            .into()),
847                        },
848                    }
849                }
850                (_, _) => Err(ParseError::ToAST("data should not be empty".to_string()).into()),
851            },
852            cst::Relation::Like { target, pattern } => match (target, pattern) {
853                (
854                    ASTNode {
855                        node: Some(target), ..
856                    },
857                    ASTNode {
858                        node: Some(pattern),
859                        ..
860                    },
861                ) => {
862                    let target_expr = target.try_into()?;
863                    let pat_expr: Expr = pattern.try_into()?;
864                    let pat_str = pat_expr.into_string_literal().ok_or_else(|| {
865                        ParseError::ToAST("`like` RHS should be a string literal".to_string())
866                    })?;
867                    Ok(Expr::like(target_expr, pat_str))
868                }
869                (_, _) => Err(ParseError::ToAST("data should not be empty".to_string()).into()),
870            },
871        }
872    }
873}
874
875impl TryFrom<cst::Add> for Expr {
876    type Error = ParseErrors;
877    fn try_from(a: cst::Add) -> Result<Expr, ParseErrors> {
878        let mut expr = match a.initial.node {
879            Some(m) => m.try_into(),
880            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
881        }?;
882        for (op, node) in a.extended {
883            let rhs = match node.node {
884                Some(m) => m.try_into(),
885                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
886            }?;
887            match op {
888                cst::AddOp::Plus => {
889                    expr = Expr::add(expr, rhs);
890                }
891                cst::AddOp::Minus => {
892                    expr = Expr::sub(expr, rhs);
893                }
894            }
895        }
896        Ok(expr)
897    }
898}
899
900/// Returns `Some` if this is just a cst::Name. For example the
901/// `foobar` in `context has foobar`
902fn is_add_name(add: cst::Add) -> Option<cst::Name> {
903    if add.extended.is_empty() {
904        match add.initial.node {
905            Some(mult) => is_mult_name(mult),
906            None => None,
907        }
908    } else {
909        None
910    }
911}
912
913/// Returns `Some` if this is just a cst::Name. For example the
914/// `foobar` in `context has foobar`
915fn is_mult_name(mult: cst::Mult) -> Option<cst::Name> {
916    if mult.extended.is_empty() {
917        match mult.initial.node {
918            Some(unary) => is_unary_name(unary),
919            None => None,
920        }
921    } else {
922        None
923    }
924}
925
926/// Returns `Some` if this is just a cst::Name. For example the
927/// `foobar` in `context has foobar`
928fn is_unary_name(unary: cst::Unary) -> Option<cst::Name> {
929    if unary.op.is_none() {
930        match unary.item.node {
931            Some(mem) => is_mem_name(mem),
932            None => None,
933        }
934    } else {
935        None
936    }
937}
938
939/// Returns `Some` if this is just a cst::Name. For example the
940/// `foobar` in `context has foobar`
941fn is_mem_name(mem: cst::Member) -> Option<cst::Name> {
942    if mem.access.is_empty() {
943        match mem.item.node {
944            Some(primary) => is_primary_name(primary),
945            None => None,
946        }
947    } else {
948        None
949    }
950}
951
952/// Returns `Some` if this is just a cst::Name. For example the
953/// `foobar` in `context has foobar`
954fn is_primary_name(primary: cst::Primary) -> Option<cst::Name> {
955    match primary {
956        cst::Primary::Name(node) => node.node,
957        _ => None,
958    }
959}
960
961impl TryFrom<cst::Mult> for Expr {
962    type Error = ParseErrors;
963    fn try_from(m: cst::Mult) -> Result<Expr, ParseErrors> {
964        let mut expr = match m.initial.node {
965            Some(u) => u.try_into(),
966            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
967        }?;
968        for (op, node) in m.extended {
969            let rhs = match node.node {
970                Some(u) => u.try_into(),
971                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
972            }?;
973            match op {
974                cst::MultOp::Times => {
975                    expr = Expr::mul(expr, rhs);
976                }
977                cst::MultOp::Divide => {
978                    return Err(ParseError::ToAST("division is not supported".to_string()).into())
979                }
980                cst::MultOp::Mod => {
981                    return Err(ParseError::ToAST("modulo is not supported".to_string()).into())
982                }
983            }
984        }
985        Ok(expr)
986    }
987}
988
989impl TryFrom<cst::Unary> for Expr {
990    type Error = ParseErrors;
991    fn try_from(u: cst::Unary) -> Result<Expr, ParseErrors> {
992        let inner = match u.item.node {
993            Some(m) => m.try_into(),
994            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
995        }?;
996        match u.op {
997            Some(cst::NegOp::Bang(0)) => Ok(inner),
998            Some(cst::NegOp::Bang(1)) => Ok(Expr::not(inner)),
999            Some(cst::NegOp::Bang(2)) => {
1000                // not safe to collapse !! to nothing
1001                Ok(Expr::not(Expr::not(inner)))
1002            }
1003            Some(cst::NegOp::Bang(n)) => {
1004                if n % 2 == 0 {
1005                    // safe to collapse to !! but not to nothing
1006                    Ok(Expr::not(Expr::not(inner)))
1007                } else {
1008                    // safe to collapse to !
1009                    Ok(Expr::not(inner))
1010                }
1011            }
1012            Some(cst::NegOp::Dash(0)) => Ok(inner),
1013            Some(cst::NegOp::Dash(mut num_dashes)) => {
1014                let inner = match inner {
1015                    Expr::ExprNoExt(ExprNoExt::Value(JSONValue::Long(n))) if n != std::i64::MIN => {
1016                        // collapse the negated literal into a single negative literal.
1017                        // Important for multiplication-by-constant to allow multiplication by negative constants.
1018                        num_dashes -= 1;
1019                        Expr::lit(JSONValue::Long(-n))
1020                    }
1021                    _ => inner,
1022                };
1023                match num_dashes {
1024                    0 => Ok(inner),
1025                    1 => Ok(Expr::neg(inner)),
1026                    2 => {
1027                        // not safe to collapse `--` to nothing
1028                        Ok(Expr::neg(Expr::neg(inner)))
1029                    }
1030                    n => {
1031                        if n % 2 == 0 {
1032                            // safe to collapse to `--` but not to nothing
1033                            Ok(Expr::neg(Expr::neg(inner)))
1034                        } else {
1035                            // safe to collapse to -
1036                            Ok(Expr::neg(inner))
1037                        }
1038                    }
1039                }
1040            }
1041            Some(cst::NegOp::OverBang) => Err(ParseError::ToAST("Too many !'s".to_string()).into()),
1042            Some(cst::NegOp::OverDash) => Err(ParseError::ToAST("Too many -'s".to_string()).into()),
1043            None => Ok(inner),
1044        }
1045    }
1046}
1047
1048/// Convert the given `cst::Primary` into either a (possibly namespaced)
1049/// function name, or an `Expr`.
1050///
1051/// (Upstream, the case where the `Primary` is a function name needs special
1052/// handling, because in that case it is not a valid expression. In all other
1053/// cases a `Primary` can be converted into an `Expr`.)
1054fn interpret_primary(p: cst::Primary) -> Result<Either<ast::Name, Expr>, ParseErrors> {
1055    match p {
1056        cst::Primary::Literal(ASTNode { node, .. }) => match node {
1057            Some(lit) => Ok(Either::Right(lit.try_into()?)),
1058            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1059        },
1060        cst::Primary::Ref(ASTNode { node, .. }) => match node {
1061            Some(cst::Ref::Uid { path, eid }) => {
1062                let mut errs = vec![];
1063                let maybe_name = path.to_name(&mut errs);
1064                let maybe_eid = eid.as_valid_string(&mut errs);
1065
1066                if errs.is_empty() {
1067                    let name = maybe_name.expect("should be Some since errs.is_empty()");
1068                    let eid = maybe_eid.expect("should be Some since errs.is_empty()");
1069                    Ok(Either::Right(Expr::lit(JSONValue::EntityEscape {
1070                        __entity: TypeAndId::from(ast::EntityUID::from_components(
1071                            name,
1072                            ast::Eid::new(eid.clone()),
1073                        )),
1074                    })))
1075                } else {
1076                    Err(ParseErrors(errs))
1077                }
1078            }
1079            Some(cst::Ref::Ref { .. }) => {
1080                Err(ParseError::ToAST("entity-lookup syntax is not supported".to_string()).into())
1081            }
1082            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1083        },
1084        cst::Primary::Name(ASTNode { node, .. }) => match node {
1085            Some(name) => match (&name.path[..], name.name.node) {
1086                (&[], Some(cst::Ident::Principal)) => {
1087                    Ok(Either::Right(Expr::var(ast::Var::Principal)))
1088                }
1089                (&[], Some(cst::Ident::Action)) => Ok(Either::Right(Expr::var(ast::Var::Action))),
1090                (&[], Some(cst::Ident::Resource)) => {
1091                    Ok(Either::Right(Expr::var(ast::Var::Resource)))
1092                }
1093                (&[], Some(cst::Ident::Context)) => Ok(Either::Right(Expr::var(ast::Var::Context))),
1094                (path, Some(cst::Ident::Ident(id))) => Ok(Either::Left(ast::Name::new(
1095                    id.parse().map_err(ParseErrors)?,
1096                    path.iter()
1097                        .map(|ASTNode { node, .. }| {
1098                            node.as_ref()
1099                                .ok_or_else(|| {
1100                                    ParseErrors(vec![ParseError::ToAST(
1101                                        "node should not be empty".to_string(),
1102                                    )])
1103                                })
1104                                .and_then(|id| id.to_string().parse().map_err(ParseErrors))
1105                        })
1106                        .collect::<Result<Vec<ast::Id>, _>>()?,
1107                ))),
1108                (path, Some(id)) => Err(ParseError::ToAST(format!(
1109                    "{} is not a valid expr",
1110                    cst::Name {
1111                        path: path.to_vec(),
1112                        name: ASTNode::new(Some(id), 0, 0)
1113                    }
1114                ))
1115                .into()),
1116                (_, None) => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1117            },
1118            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1119        },
1120        cst::Primary::Slot(ASTNode { node, .. }) => match node {
1121            Some(cst::Slot::Principal) => Ok(Either::Right(Expr::slot(ast::SlotId::principal()))),
1122            Some(cst::Slot::Resource) => Ok(Either::Right(Expr::slot(ast::SlotId::resource()))),
1123            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1124        },
1125        cst::Primary::Expr(ASTNode { node, .. }) => match node {
1126            Some(e) => Ok(Either::Right(e.try_into()?)),
1127            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1128        },
1129        cst::Primary::EList(nodes) => nodes
1130            .into_iter()
1131            .map(|node| match node.node {
1132                Some(e) => e.try_into(),
1133                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1134            })
1135            .collect::<Result<Vec<Expr>, _>>()
1136            .map(Expr::set)
1137            .map(Either::Right),
1138        cst::Primary::RInits(nodes) => nodes
1139            .into_iter()
1140            .map(|node| match node.node {
1141                Some(cst::RecInit(k, v)) => {
1142                    let mut errs = vec![];
1143                    let s = k
1144                        .to_expr_or_special(&mut errs)
1145                        .and_then(|es| es.into_valid_attr(&mut errs));
1146                    if !errs.is_empty() {
1147                        Err(ParseErrors(errs))
1148                    } else {
1149                        match (s, v.node) {
1150                            (Some(s), Some(e)) => Ok((s, e.try_into()?)),
1151                            (_, _) => {
1152                                Err(ParseError::ToAST("node should not be empty".to_string())
1153                                    .into())
1154                            }
1155                        }
1156                    }
1157                }
1158                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1159            })
1160            .collect::<Result<HashMap<SmolStr, Expr>, ParseErrors>>()
1161            .map(Expr::record)
1162            .map(Either::Right),
1163    }
1164}
1165
1166impl TryFrom<cst::Member> for Expr {
1167    type Error = ParseErrors;
1168    fn try_from(m: cst::Member) -> Result<Expr, ParseErrors> {
1169        let mut item: Either<ast::Name, Expr> = match m.item.node {
1170            Some(p) => interpret_primary(p),
1171            None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1172        }?;
1173        for access in m.access {
1174            match access.node {
1175                Some(cst::MemAccess::Field(ASTNode { node, .. })) => match node {
1176                    Some(cst::Ident::Ident(i)) => {
1177                        item = match item {
1178                            Either::Left(name) => {
1179                                return Err(ParseError::ToAST(format!(
1180                                    "{name}.{i} is not a valid expression"
1181                                ))
1182                                .into())
1183                            }
1184                            Either::Right(expr) => Either::Right(Expr::get_attr(expr, i)),
1185                        };
1186                    }
1187                    Some(_i) => {
1188                        return Err(ParseError::ToAST("Invalid Identifier".to_string()).into())
1189                    }
1190                    None => {
1191                        return Err(ParseError::ToAST("node should not be empty".to_string()).into())
1192                    }
1193                },
1194                Some(cst::MemAccess::Call(args)) => {
1195                    // we have item(args).  We hope item is either:
1196                    //   - an `ast::Name`, in which case we have a standard function call
1197                    //   - or an expr of the form `x.y`, in which case y is the method
1198                    //      name and not a field name. In the previous iteration of the
1199                    //      `for` loop we would have made `item` equal to
1200                    //      `Expr::GetAttr(x, y)`. Now we have to undo that to make a
1201                    //      method call instead.
1202                    item = match item {
1203                        Either::Left(name) => Either::Right(Expr::ext_call(
1204                            name.to_string().into(),
1205                            args.into_iter()
1206                                .map(|ASTNode { node, .. }| match node {
1207                                    Some(expr) => expr.try_into(),
1208                                    None => Err(ParseError::ToAST(
1209                                        "node should not be empty".to_string(),
1210                                    )
1211                                    .into()),
1212                                })
1213                                .collect::<Result<Vec<_>, _>>()?,
1214                        )),
1215                        Either::Right(Expr::ExprNoExt(ExprNoExt::GetAttr { left, attr })) => {
1216                            let mut args = args
1217                                .into_iter()
1218                                .map(|node| match node.node {
1219                                    Some(arg) => arg.try_into(),
1220                                    None => Err(ParseError::ToAST(
1221                                        "node should not be empty".to_string(),
1222                                    )
1223                                    .into()),
1224                                })
1225                                .collect::<Result<Vec<Expr>, ParseErrors>>()?;
1226                            match attr.as_str() {
1227                                "contains" => match args.len() {
1228                                    1 => {
1229                                        let arg = args
1230                                            .into_iter()
1231                                            .next()
1232                                            .expect("already checked there is 1 arg");
1233                                        Either::Right(Expr::contains(left, arg))
1234                                    }
1235                                    0 => {
1236                                        return Err(ParseError::ToAST(
1237                                            "contains() must have an argument".to_string(),
1238                                        )
1239                                        .into())
1240                                    }
1241                                    _ => {
1242                                        return Err(ParseError::ToAST(
1243                                            "contains() must have only one argument".to_string(),
1244                                        )
1245                                        .into())
1246                                    }
1247                                },
1248                                "containsAll" => match args.len() {
1249                                    1 => {
1250                                        let arg = args
1251                                            .into_iter()
1252                                            .next()
1253                                            .expect("already checked there is 1 arg");
1254                                        Either::Right(Expr::contains_all(left, arg))
1255                                    }
1256                                    0 => {
1257                                        return Err(ParseError::ToAST(
1258                                            "containsAll() must have an argument".to_string(),
1259                                        )
1260                                        .into())
1261                                    }
1262                                    _ => {
1263                                        return Err(ParseError::ToAST(
1264                                            "containsAll() must have only one argument".to_string(),
1265                                        )
1266                                        .into())
1267                                    }
1268                                },
1269                                "containsAny" => match args.len() {
1270                                    1 => {
1271                                        let arg = args
1272                                            .into_iter()
1273                                            .next()
1274                                            .expect("already checked there is 1 arg");
1275                                        Either::Right(Expr::contains_any(left, arg))
1276                                    }
1277                                    0 => {
1278                                        return Err(ParseError::ToAST(
1279                                            "containsAny() must have an argument".to_string(),
1280                                        )
1281                                        .into())
1282                                    }
1283                                    _ => {
1284                                        return Err(ParseError::ToAST(
1285                                            "containsAny() must have only one argument".to_string(),
1286                                        )
1287                                        .into())
1288                                    }
1289                                },
1290                                _ => {
1291                                    // have to add the "receiver" argument as
1292                                    // first in the list for the method call
1293                                    args.insert(0, unwrap_or_clone(left));
1294                                    Either::Right(Expr::ext_call(attr, args))
1295                                }
1296                            }
1297                        }
1298                        _ => {
1299                            return Err(
1300                                ParseError::ToAST("malformed method call".to_string()).into()
1301                            )
1302                        }
1303                    };
1304                }
1305                Some(cst::MemAccess::Index(ASTNode { node, .. })) if node.is_some() => {
1306                    let s = Expr::try_from(node.unwrap())?
1307                        .into_string_literal()
1308                        .ok_or_else(|| {
1309                            ParseError::ToAST(
1310                                "attribute value must be a string literal".to_string(),
1311                            )
1312                        })?;
1313                    item = match item {
1314                        Either::Left(name) => {
1315                            return Err(ParseError::ToAST(format!(
1316                                "{name}[\"{s}\"] is not a valid expression"
1317                            ))
1318                            .into())
1319                        }
1320                        Either::Right(expr) => Either::Right(Expr::get_attr(expr, s)),
1321                    };
1322                }
1323                _ => return Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1324            }
1325        }
1326        match item {
1327            Either::Left(name) => Err(ParseError::ToAST(format!(
1328                "{name} is not a valid expression"
1329            )))?,
1330            Either::Right(expr) => Ok(expr),
1331        }
1332    }
1333}
1334
1335impl TryFrom<cst::Literal> for Expr {
1336    type Error = ParseErrors;
1337    fn try_from(lit: cst::Literal) -> Result<Expr, ParseErrors> {
1338        match lit {
1339            cst::Literal::True => Ok(Expr::lit(JSONValue::Bool(true))),
1340            cst::Literal::False => Ok(Expr::lit(JSONValue::Bool(false))),
1341            cst::Literal::Num(n) => {
1342                Ok(Expr::lit(JSONValue::Long(n.try_into().map_err(|_| {
1343                    ParseError::ToAST("numeric literal out of range".to_string())
1344                })?)))
1345            }
1346            cst::Literal::Str(ASTNode { node, .. }) => match node {
1347                Some(cst::Str::String(s)) => Ok(Expr::lit(JSONValue::String(s))),
1348                Some(_) => Err(ParseError::ToAST("invalid string".to_string()).into()),
1349                None => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1350            },
1351        }
1352    }
1353}
1354
1355impl TryFrom<cst::Name> for Expr {
1356    type Error = ParseErrors;
1357    fn try_from(name: cst::Name) -> Result<Expr, ParseErrors> {
1358        match (&name.path[..], name.name.node) {
1359            (&[], Some(cst::Ident::Principal)) => Ok(Expr::var(ast::Var::Principal)),
1360            (&[], Some(cst::Ident::Action)) => Ok(Expr::var(ast::Var::Action)),
1361            (&[], Some(cst::Ident::Resource)) => Ok(Expr::var(ast::Var::Resource)),
1362            (&[], Some(cst::Ident::Context)) => Ok(Expr::var(ast::Var::Context)),
1363            (path, Some(id)) => Err(ParseError::ToAST(format!(
1364                "{} is not a valid expr",
1365                cst::Name {
1366                    path: path.to_vec(),
1367                    name: ASTNode::new(Some(id), 0, 0)
1368                }
1369            ))
1370            .into()),
1371            (_, None) => Err(ParseError::ToAST("node should not be empty".to_string()).into()),
1372        }
1373    }
1374}