ripex 0.2.0

Multi-language structural parsing and fact extraction.
Documentation
use crate::c::ast::*;

pub trait Fold {
    fn fold_expr(&mut self, expr: Expr) -> Expr;
    fn fold_stmt(&mut self, stmt: Stmt) -> Stmt;
}

fn fold_block(folder: &mut dyn Fold, block: Block) -> Block {
    Block {
        stmts: block
            .stmts
            .into_iter()
            .map(|s| folder.fold_stmt(s))
            .collect(),
        span: block.span,
    }
}

pub fn fold_expr(folder: &mut dyn Fold, expr: Expr) -> Expr {
    match expr {
        Expr::Binary(left, op, right, span) => Expr::Binary(
            Box::new(folder.fold_expr(*left)),
            op,
            Box::new(folder.fold_expr(*right)),
            span,
        ),
        Expr::Unary(op, operand, span) => {
            Expr::Unary(op, Box::new(folder.fold_expr(*operand)), span)
        }
        Expr::Call(callee, args, span) => Expr::Call(
            Box::new(folder.fold_expr(*callee)),
            args.into_iter().map(|a| folder.fold_expr(a)).collect(),
            span,
        ),
        Expr::Index(arr, idx, span) => Expr::Index(
            Box::new(folder.fold_expr(*arr)),
            Box::new(folder.fold_expr(*idx)),
            span,
        ),
        Expr::Member(obj, name, span) => Expr::Member(Box::new(folder.fold_expr(*obj)), name, span),
        Expr::Arrow(obj, name, span) => Expr::Arrow(Box::new(folder.fold_expr(*obj)), name, span),
        Expr::Deref(e, span) => Expr::Deref(Box::new(folder.fold_expr(*e)), span),
        Expr::Ref(e, span) => Expr::Ref(Box::new(folder.fold_expr(*e)), span),
        Expr::Cast(e, t, span) => Expr::Cast(Box::new(folder.fold_expr(*e)), t, span),
        Expr::Sizeof(e, span) => Expr::Sizeof(Box::new(folder.fold_expr(*e)), span),
        Expr::Alignof(e, span) => Expr::Alignof(Box::new(folder.fold_expr(*e)), span),
        Expr::Ternary(cond, then, els, span) => Expr::Ternary(
            Box::new(folder.fold_expr(*cond)),
            Box::new(folder.fold_expr(*then)),
            Box::new(folder.fold_expr(*els)),
            span,
        ),
        Expr::Comma(exprs, span) => Expr::Comma(
            exprs.into_iter().map(|e| folder.fold_expr(e)).collect(),
            span,
        ),
        Expr::StmtExpr(stmts, span) => Expr::StmtExpr(
            stmts.into_iter().map(|s| folder.fold_stmt(s)).collect(),
            span,
        ),
        Expr::Paren(e, span) => Expr::Paren(Box::new(folder.fold_expr(*e)), span),
        Expr::Assign(left, right, span) => Expr::Assign(
            Box::new(folder.fold_expr(*left)),
            Box::new(folder.fold_expr(*right)),
            span,
        ),
        other => other,
    }
}

pub fn fold_stmt(folder: &mut dyn Fold, stmt: Stmt) -> Stmt {
    match stmt {
        Stmt::Expr(e, span) => Stmt::Expr(folder.fold_expr(e), span),
        Stmt::Decl(f, span) => Stmt::Decl(f, span),
        Stmt::VarDecl(v, span) => Stmt::VarDecl(v, span),
        Stmt::If(cond, body, alt, span) => Stmt::If(
            folder.fold_expr(cond),
            Box::new(folder.fold_stmt(*body)),
            alt.map(|a| Box::new(folder.fold_stmt(*a))),
            span,
        ),
        Stmt::Switch(test, cases, span) => Stmt::Switch(folder.fold_expr(test), cases, span),
        Stmt::While(cond, body, span) => Stmt::While(
            folder.fold_expr(cond),
            Box::new(folder.fold_stmt(*body)),
            span,
        ),
        Stmt::Do(body, test, span) => Stmt::Do(
            Box::new(folder.fold_stmt(*body)),
            folder.fold_expr(test),
            span,
        ),
        Stmt::For(init, test, update, body, span) => Stmt::For(
            init.map(|i| Box::new(folder.fold_stmt(*i))),
            test.map(|t| folder.fold_expr(t)),
            update.map(|u| Box::new(folder.fold_stmt(*u))),
            Box::new(folder.fold_stmt(*body)),
            span,
        ),
        Stmt::Return(e, span) => Stmt::Return(e.map(|e| folder.fold_expr(e)), span),
        Stmt::Block(b, span) => Stmt::Block(fold_block(folder, b), span),
        other => other,
    }
}