doublify_toolkit/filtering/
mod.rs1mod parser;
23mod scanner;
24mod tokenizer;
25
26pub use filtering::parser::{Expression, InExpression, Literal, OrExpression, VariableDeclaration,
27 VariableDeclarationKind, parse};
28pub use filtering::scanner::{Kind, Token, scan};
29pub use filtering::tokenizer::tokenize;
30
31use std::collections::HashMap;
32
33#[derive(Debug, PartialEq)]
35pub enum Operation {
36 Equal,
38 Or,
40 In,
42}
43
44#[derive(Debug, PartialEq)]
46pub struct Filter {
47 pub operation: Operation,
49 pub bindings: Vec<Literal>,
51}
52
53#[derive(Debug, PartialEq)]
55pub struct Query {
56 pub bindings: HashMap<String, Filter>,
58}
59
60fn traverse_identifier(name: &Literal, children: &Option<Box<Expression>>) -> String {
65 let default = &String::new();
66 let new_name = if let Some(box Expression::Literal(Literal::Identifier(ref name))) = *children {
67 name
68 } else if let Literal::Identifier(ref name) = *name {
69 name
70 } else {
71 default
72 };
73
74 new_name.to_owned()
75}
76
77fn traverse_children(filter: &mut Filter, children: &Vec<Box<Expression>>) {
79 for child in children {
80 match *child {
81 box Expression::Literal(ref binding) => filter.bindings.push(binding.to_owned()),
82 _ => {}
83 }
84 }
85}
86
87fn traverse_variable_declaration(VariableDeclaration { ref mut kind, ref name, ref mut children }: VariableDeclaration) -> (String, Filter){
89 let new_name = traverse_identifier(name, children);
90
91 let mut filter = Filter {
92 operation: Operation::Equal,
93 bindings: vec![],
94 };
95
96 children
97 .take()
98 .map(
99 |expr| match expr {
100 box Expression::OrExpression(OrExpression { ref children }) => {
101 filter.operation = Operation::Or;
102 traverse_children(&mut filter, children);
103 }
104 box Expression::InExpression(InExpression { ref children }) => {
105 filter.operation = Operation::In;
106 traverse_children(&mut filter, children);
107 }
108 box Expression::Literal(binding) => {
109 use self::VariableDeclarationKind::*;
110
111 let traverse = |kind| {
112 Literal::Boolean(
113 match kind {
114 IsKeyword => true,
115 NotKeyword => false,
116 },
117 )
118 };
119
120 filter
121 .bindings
122 .push(kind.take().map_or(binding, traverse))
123 }
124 _ => {}
125 },
126 );
127
128 (new_name, filter)
129}
130
131pub fn parse_query(raw_query: &str) -> Query {
133 let tokens = tokenize(raw_query);
134 let source = parse(tokens);
135 let mut bindings: HashMap<String, Filter> = HashMap::new();
136
137 for node in source.body {
138 if let Expression::VariableDeclaration(variable_declaration) = *node {
139 let (name, filter) = traverse_variable_declaration(variable_declaration);
140
141 bindings.insert(name, filter);
142 }
143 }
144
145 Query { bindings: bindings }
146}