rscel 1.0.8

Cel interpreter in rust
Documentation
use rscel::{
    Addition, AstNode, ConditionalAnd, ConditionalOr, Expr, ExprList, Ident, Member, MemberPrime,
    Multiplication, NegList, NotList, ObjInit, ObjInits, Primary, Relation, Unary,
};

fn main() {
    let args: Vec<_> = std::env::args().collect();

    if args.len() < 2 {
        eprintln!("Usage: {} <prog>", args[0]);
        return;
    }

    let prog = rscel::Program::from_source(&args[1]).expect("Failed to compile");
    let ast = prog.details().ast().unwrap();

    AstDumper::with_source(&args[1]).dump_expr_node(ast, 0);
}

struct AstDumper<'a> {
    source: &'a str,
}

impl<'a> AstDumper<'a> {
    fn with_source(s: &'a str) -> Self {
        AstDumper { source: s }
    }

    fn dump_expr_node(&self, node: &AstNode<Expr>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Expr::Unary(nxt) => self.dump_or_node(nxt, depth + 1),
            Expr::Ternary {
                condition,
                true_clause,
                false_clause,
            } => {
                self.dump_or_node(condition, depth + 1);
                self.dump_or_node(true_clause, depth + 1);
                self.dump_expr_node(false_clause, depth + 1);
            }
            Expr::Match { .. } => todo!(),
        }
    }

    fn dump_or_node(&self, node: &AstNode<ConditionalOr>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            ConditionalOr::Unary(nxt) => self.dump_and_node(nxt, depth + 1),
            ConditionalOr::Binary { lhs, rhs } => {
                self.dump_or_node(lhs, depth + 1);
                self.dump_and_node(rhs, depth + 1)
            }
        }
    }

    fn dump_and_node(&self, node: &AstNode<ConditionalAnd>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            ConditionalAnd::Unary(nxt) => self.dump_relation(nxt, depth + 1),
            ConditionalAnd::Binary { lhs, rhs } => {
                self.dump_and_node(lhs, depth + 1);
                self.dump_relation(rhs, depth + 1);
            }
        }
    }

    fn dump_relation(&self, node: &AstNode<Relation>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Relation::Unary(nxt) => self.dump_addition(nxt, depth + 1),
            Relation::Binary { lhs, op: _op, rhs } => {
                self.dump_relation(lhs, depth + 1);
                self.dump_addition(rhs, depth + 1);
            }
        }
    }

    fn dump_addition(&self, node: &AstNode<Addition>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Addition::Unary(nxt) => self.dump_multiplication(nxt, depth + 1),
            Addition::Binary { lhs, op: _op, rhs } => {
                self.dump_addition(lhs, depth + 1);
                self.dump_multiplication(rhs, depth + 1);
            }
        }
    }

    fn dump_multiplication(&self, node: &AstNode<Multiplication>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Multiplication::Unary(nxt) => self.dump_uniary(nxt, depth + 1),
            Multiplication::Binary { lhs, op: _op, rhs } => {
                self.dump_multiplication(lhs, depth + 1);
                self.dump_uniary(rhs, depth + 1);
            }
        }
    }

    fn dump_uniary(&self, node: &AstNode<Unary>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Unary::Member(nxt) => self.dump_member(nxt, depth + 1),
            Unary::NegMember { negs, member } => {
                self.dump_neg(negs, depth + 1);
                self.dump_member(member, depth + 1);
            }
            Unary::NotMember { nots, member } => {
                self.dump_not(nots, depth + 1);
                self.dump_member(member, depth + 1);
            }
        }
    }

    fn dump_neg(&self, node: &AstNode<NegList>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            NegList::List { tail } => self.dump_neg(tail, depth + 1),
            NegList::EmptyList => {}
        }
    }

    fn dump_not(&self, node: &AstNode<NotList>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            NotList::List { tail } => self.dump_not(tail, depth + 1),
            NotList::EmptyList => {}
        }
    }

    fn dump_member(&self, node: &AstNode<Member>, depth: usize) {
        self.format_output(node, depth);
        self.dump_primary(&node.node().primary, depth + 1);
        for member in node.node().member.iter() {
            self.dump_member_prime(member, depth + 1);
        }
    }

    fn dump_primary(&self, node: &AstNode<Primary>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            Primary::Type => {}
            Primary::Ident(_) => {}
            Primary::Parens(expr) => self.dump_expr_node(expr, depth + 1),
            Primary::ListConstruction(exprs) => self.dump_expr_list(exprs, depth + 1),
            Primary::ObjectInit(objinits) => self.dump_obj_inits(objinits, depth + 1),
            Primary::Literal(_) => {}
        }
    }

    fn dump_member_prime(&self, node: &AstNode<MemberPrime>, depth: usize) {
        self.format_output(node, depth);
        match node.node() {
            MemberPrime::MemberAccess { ident } => {
                self.dump_ident(&ident, depth + 1);
            }
            MemberPrime::Call { call } => self.dump_expr_list(call, depth + 1),
            MemberPrime::ArrayAccess { access } => self.dump_expr_node(access, depth + 1),
            MemberPrime::Empty => {}
        }
    }

    fn dump_ident(&self, node: &AstNode<Ident>, depth: usize) {
        self.format_output(node, depth);
    }

    fn dump_expr_list(&self, node: &AstNode<ExprList>, depth: usize) {
        self.format_output(node, depth);
        for expr in node.node().exprs.iter() {
            self.dump_expr_node(expr, depth + 1);
        }
    }

    fn dump_obj_inits(&self, node: &AstNode<ObjInits>, depth: usize) {
        self.format_output(node, depth);
        for init in node.node().inits.iter() {
            self.dump_obj_init(init, depth + 1);
        }
    }

    fn dump_obj_init(&self, node: &AstNode<ObjInit>, depth: usize) {
        self.format_output(node, depth);
        self.dump_expr_node(&node.node().key, depth + 1);
        self.dump_expr_node(&node.node().value, depth + 1);
    }

    fn format_output<T>(&self, ast: &AstNode<T>, depth: usize) {
        let spacing: String = std::iter::repeat(' ').take(depth).collect();

        println!(
            "{} {} -- '{}'::{},{}",
            spacing,
            std::any::type_name::<T>().split("::").last().unwrap(),
            &self.source.to_string()[ast.start().col()..ast.end().col()],
            ast.start().col(),
            ast.end().col()
        );
    }
}