src/filter/dsl/parser/mod.rs

//! Parser entry point.
//!
//! The parser is split into a [`lexer`] that emits a stream of tokens and a
//! [`grammar`] module that walks those tokens recursively. The public surface
//! is the [`parse`] function below.

pub mod grammar;
pub mod lexer;

use super::ast::Expr;
use super::error::{DslError, DslResult};

/// Parse an input string into an [`Expr`] AST.
///
/// Returns [`DslError::Syntax`] on any lexing or grammar failure. The error
/// includes a 1-indexed column number for pretty-print purposes.
pub fn parse(input: &str) -> DslResult<Expr> {
    if input.trim().is_empty() {
        return Err(DslError::Syntax {
            column: 1,
            message: "empty filter expression".into(),
        });
    }
    let tokens = lexer::tokenize(input)?;
    grammar::parse_tokens(tokens)
}