rtlola-parser 0.4.0

A parser for RTLola specifications.
Documentation
use rtlola_reporting::Span;

use crate::{
    ast::{
        AnnotatedPacingType, BinOp, EvalSpec, Expression, ExpressionKind, FunctionName, Ident,
        InstanceOperation, InstanceSelection, Literal, Offset, Type, UnOp, WindowOperation,
    },
    RtLolaAst,
};

#[derive(Debug)]
pub(crate) struct Builder<'a> {
    pub(crate) span: Span,
    pub(crate) ast: &'a RtLolaAst,
}

impl<'a> Builder<'a> {
    pub(crate) fn new(span: Span, ast: &'a RtLolaAst) -> Self {
        Self { span, ast }
    }

    pub(crate) fn ident(&self, ident: Ident) -> Expression {
        Expression {
            kind: ExpressionKind::Ident(ident),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn function(
        &self,
        func_name: FunctionName,
        ty: Vec<Type>,
        parameters: Vec<Expression>,
    ) -> Expression {
        Expression {
            kind: ExpressionKind::Function(func_name, ty, parameters),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn method(
        &self,
        base: Expression,
        func_name: FunctionName,
        ty: Vec<Type>,
        parameters: Vec<Expression>,
    ) -> Expression {
        Expression {
            kind: ExpressionKind::Method(Box::new(base), func_name, ty, parameters),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn last(
        &self,
        stream: Ident,
        params: Vec<Expression>,
        or: Expression,
    ) -> Expression {
        let stream_expr = self.parameter_use(stream, params);
        self.method(
            stream_expr,
            FunctionName {
                name: Ident::new("last".into(), self.span.to_indirect()),
                arg_names: vec![Some(Ident::new("or".into(), self.span.to_indirect()))],
            },
            Vec::new(),
            vec![or],
        )
    }

    pub(crate) fn parameter_use(&self, stream: Ident, params: Vec<Expression>) -> Expression {
        if params.is_empty() {
            self.ident(stream)
        } else {
            self.function(
                FunctionName {
                    name: stream,
                    arg_names: vec![None; params.len()],
                },
                vec![],
                params,
            )
        }
    }

    pub(crate) fn sync(&self, stream: Ident, params: Vec<Expression>) -> Expression {
        Expression {
            kind: ExpressionKind::StreamAccess(
                Box::new(self.parameter_use(stream, params)),
                crate::ast::StreamAccessKind::Sync,
            ),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn offset(&self, stream: Expression, offset: Offset) -> Expression {
        Expression {
            kind: ExpressionKind::Offset(Box::new(stream), offset),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn default(&self, expr: Expression, dft: Expression) -> Expression {
        Expression {
            kind: ExpressionKind::Default(Box::new(expr), Box::new(dft)),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    fn unary(&self, op: UnOp, expr: Expression) -> Expression {
        Expression {
            kind: ExpressionKind::Unary(op, Box::new(expr)),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn not(&self, expr: Expression) -> Expression {
        self.unary(UnOp::Not, expr)
    }

    pub(crate) fn parentesized(&self, expr: Expression) -> Expression {
        Expression {
            kind: ExpressionKind::ParenthesizedExpression(Box::new(expr)),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    fn binary(&self, op: BinOp, lhs: Expression, rhs: Expression) -> Expression {
        Expression {
            kind: ExpressionKind::Binary(op, Box::new(lhs), Box::new(rhs)),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn or(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Or, lhs, rhs)
    }

    pub(crate) fn and(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::And, lhs, rhs)
    }

    pub(crate) fn eq(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Eq, lhs, rhs)
    }

    pub(crate) fn add(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Add, lhs, rhs)
    }

    pub(crate) fn sub(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Sub, lhs, rhs)
    }

    pub(crate) fn mul(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Mul, lhs, rhs)
    }

    pub(crate) fn div(&self, lhs: Expression, rhs: Expression) -> Expression {
        self.binary(BinOp::Div, lhs, rhs)
    }

    pub(crate) fn sliding_window(
        &self,
        stream: Expression,
        duration: Expression,
        wait: bool,
        aggregation: WindowOperation,
    ) -> Expression {
        Expression {
            kind: ExpressionKind::SlidingWindowAggregation {
                expr: Box::new(stream),
                duration: Box::new(duration),
                wait,
                aggregation,
            },
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn instance_aggregation(
        &self,
        stream: Expression,
        selection: InstanceSelection,
        aggregation: InstanceOperation,
    ) -> Expression {
        Expression {
            kind: ExpressionKind::InstanceAggregation {
                expr: Box::new(stream),
                selection,
                aggregation,
            },
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn literal(&self, v: Literal) -> Expression {
        Expression {
            kind: ExpressionKind::Lit(v),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn if_then_else(
        &self,
        cond: Expression,
        cons: Expression,
        alt: Expression,
    ) -> Expression {
        Expression {
            kind: ExpressionKind::Ite(Box::new(cond), Box::new(cons), Box::new(alt)),
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }

    pub(crate) fn eval_spec(
        &self,
        condition: Option<Expression>,
        annotated_pacing: AnnotatedPacingType,
        eval_expression: Option<Expression>,
    ) -> EvalSpec {
        EvalSpec {
            annotated_pacing,
            condition,
            eval_expression,
            id: self.ast.next_id(),
            span: self.span.to_indirect(),
        }
    }
}