common-expression-language 0.1.0

A Rust implementation of the Common Expression Language (CEL)
Documentation
use std::str::FromStr;
use crate::ast::{RelationOp, ArithmeticOp, Expression, UnaryOp, Member, Literal};

grammar;


pub Expression: Box<Expression> = {
    <left:Expression> <op:ArithmeticOp> <right:Primary> => Expression::Arithmetic{<>}.into(),
    <left:Expression> <op:RelationOp> <right:Primary> => Expression::Relation{<>}.into(),
    <condition:Expression> "?" <left:Primary> ":" <right:Primary> => Expression::Ternary{<>}.into(),
    <left:Expression> "||" <right:Primary> => Expression::Or{<>}.into(),
    <left:Expression> "&&" <right:Primary> => Expression::And{<>}.into(),
    <op:UnaryOp> <right:Primary> => Expression::Unary{<>}.into(),

    Member,
};

pub Member: Box<Expression> = {
    Primary,
    <primary:Member> "." <identifier:Ident> => Expression::Member{primary, member: Member::Attribute{identifier}}.into(),
    <primary:Member> "." <identifier:Ident> "(" <arguments:CommaSeparated<Expression>> ")" => Expression::Member{primary, member: Member::Function{identifier, arguments}}.into(),
    <primary:Member> "[" <expression:Expression> "]" => Expression::Member{primary, member: Member::Index{expression}}.into(),
    <primary:Member> "{" <fields:CommaSeparated<FieldInits>> "}" => Expression::Member{primary, member: Member::Fields{fields}}.into(),
}

pub Primary: Box<Expression> = {
    "."? <Ident> => Expression::Ident(<>).into(),
    Literal => Expression::Literal(<>).into(),
    "[" <members:CommaSeparated<Expression>> "]" => Expression::List{<>}.into(),
    "{" <fields:CommaSeparated<MapInits>> "}" => Expression::Map{<>}.into(),
    "(" <Expression> ")"
}

pub FieldInits: (String, Box<Expression>) = {
    <Ident> ":" <Expression>
}

pub MapInits: (Box<Expression>, Box<Expression>) = {
    <Expression> ":" <Expression>
}

CommaSeparated<T>: Vec<T> = {
    <v:(<T> ",")*> <e:T?> => match e {
        None => v,
        Some(e) => {
            let mut v = v;
            v.push(e);
            v
        }
    }
};

ArithmeticOp: ArithmeticOp = { // (3)
    "+" => ArithmeticOp::Add,
    "-" => ArithmeticOp::Subtract,
    "*" => ArithmeticOp::Multiply,
    "/" => ArithmeticOp::Divide,
    "%" => ArithmeticOp::Modulus,
};

UnaryOp: UnaryOp = {
    "!" => UnaryOp::Not,
    "!!" => UnaryOp::DoubleNot,
    "-" => UnaryOp::Minus,
    "--" => UnaryOp::DoubleMinus,
}

RelationOp: RelationOp = {
    "<" => RelationOp::LessThan,
    "<=" => RelationOp::LessThanEq,
    ">" => RelationOp::GreaterThan,
    ">=" => RelationOp::GreaterThanEq,
    "==" => RelationOp::Equals,
    "!=" => RelationOp::NotEquals,
    "in" => RelationOp::In
}

Literal: Literal = {
    r"[0-9]+" => Literal::Int(<>.parse().unwrap()),
    r"[0-9]+ [uU]" => Literal::UInt(<>.parse().unwrap()),
};

Num: i32 = {
    r"[0-9]+" => i32::from_str(<>).unwrap()
};


Ident: String = {
    r"[_a-zA-Z][_a-zA-Z0-9]*" => String::from(<>)
}