1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 ZeroDDS Contributors
//! OMG DDS content-filter-expression parser + evaluator.
//!
//! Safety classification: **SAFE** (a pure parser + evaluator, no data
//! flows from external networks without caller mediation).
//!
//! Spec: OMG DDS 1.4 §B.2.1 "Filter expressions". The syntax is a
//! SQL-92 subset, extended with `%N` parameter placeholders.
//!
//! # Current scope
//!
//! * Literals: string (`'...'`), integer (`i64`), float (`f64`),
//! boolean (`TRUE`/`FALSE`).
//! * Identifiers: dotted (`a.b.c`) — for nested field access.
//! * Parameter placeholders: `%0`, `%1`, …
//! * Comparison ops: `=`, `!=`, `<>`, `<`, `<=`, `>`, `>=`, `LIKE`.
//! * Boolean ops: `AND`, `OR`, `NOT`.
//! * Parentheses.
//! * `LIKE` wildcards: `%` (several characters), `_` (one character).
//!
//! Not in the MVP: `BETWEEN ... AND`, `IN (...)`, `IS NULL`. Those
//! follow in 3.7c.
//!
//! # Architecture
//!
//! 1. `lexer`: tokenizer. All keywords case-insensitive, string
//! literals `'...'` with `''` escape.
//! 2. `parser`: recursive descent with precedence climbing —
//! `OR` < `AND` < `NOT` < comparison < atom.
//! 3. `ast`: data types for expressions + `Value`.
//! 4. `evaluator`: `Expr::evaluate(row, params)` → `bool`; `row`
//! implements `RowAccess` (field lookup by name).
//!
//! # Usage
//!
//! ```
//! use zerodds_sql_filter::{parse, Value, RowAccess};
//! use std::collections::HashMap;
//!
//! struct MapRow(HashMap<String, Value>);
//! impl RowAccess for MapRow {
//! fn get(&self, path: &str) -> Option<Value> {
//! self.0.get(path).cloned()
//! }
//! }
//!
//! let expr = parse("color = %0 AND x > 10").expect("parse");
//! let row = MapRow(HashMap::from([
//! ("color".into(), Value::String("RED".into())),
//! ("x".into(), Value::Int(42)),
//! ]));
//! let params = [Value::String("RED".into())];
//! assert_eq!(expr.evaluate(&row, ¶ms), Ok(true));
//! ```
extern crate alloc;
pub use ;
pub use ;
pub use ;