wardenclyffe 0.1.1

A tiny Rust query engine that supports SQL-like filters, CSV scanning, projections, and a custom DSL powered by Pest.
Documentation
use pest::Parser;
use pest_derive::Parser;

use pest::iterators::Pairs;
use crate::ast::Expr;

#[derive(Parser)]
#[grammar = "query.pest"]
pub struct QueryParser;

pub fn parse_expr(input: &str) -> Expr {
    let pairs = QueryParser::parse(Rule::query, input)
        .expect("Failed to parse filter expression");

    build_expr(pairs)
}

fn build_expr(pairs: Pairs<Rule>) -> Expr {
    use Expr::*;

    for pair in pairs {
        match pair.as_rule() {
            Rule::expr => {
                return build_expr(pair.into_inner());
            }

            Rule::or_expr => {
                let mut inner = pair.into_inner();
                let mut expr = build_expr(inner.next().unwrap().into_inner());

                for next in inner {
                    expr = Or(Box::new(expr), Box::new(build_expr(next.into_inner())));
                }

                return expr;
            }

            Rule::and_expr => {
                let mut inner = pair.into_inner();
                let mut expr = build_expr(inner.next().unwrap().into_inner());

                for next in inner {
                    expr = And(Box::new(expr), Box::new(build_expr(next.into_inner())));
                }

                return expr;
            }

            Rule::cmp_expr => {
                let mut inner = pair.into_inner();
                let field = inner.next().unwrap().as_str().to_string();
                let op = inner.next().unwrap().as_str().to_string();
                let val = inner.next().unwrap().as_str().to_string();

                return Cmp {
                    field,
                    op,
                    value: val,
                };
            }

            _ => {}
        }
    }

    panic!("Empty expression");
}