Skip to content

Commit 8b22b49

Browse files
committed
feat: Implement not, in and geom_type functions in parser
1 parent 9efaff4 commit 8b22b49

1 file changed

Lines changed: 63 additions & 21 deletions

File tree

galileo/src/expr/parser.rs

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ impl<'src> FuncContext<'src> {
102102
Ok(constructor(self.get(0)?))
103103
}
104104

105+
fn args2<Arg1, Arg2>(
106+
&mut self,
107+
constructor: impl FnOnce(Arg1, Arg2) -> Expr,
108+
) -> Result<Expr, Rich<'src, char>>
109+
where
110+
Self: GetArg<'src, Arg1> + GetArg<'src, Arg2>,
111+
{
112+
Ok(constructor(self.get(0)?, self.get(1)?))
113+
}
114+
105115
fn unknown(&self) -> Result<Expr, Rich<'src, char>> {
106116
Err(Rich::custom(
107117
self.func_name_span,
@@ -147,28 +157,27 @@ trait GetArg<'src, T> {
147157
fn get(&mut self, index: usize) -> Result<T, Rich<'src, char>>;
148158
}
149159

150-
impl<'src> GetArg<'src, String> for FuncContext<'src> {
151-
fn get(&mut self, index: usize) -> Result<String, Rich<'src, char>> {
152-
let arg = self.get_arg(index)?;
153-
if let FuncArgument::Expression(Expr::Literal(ExprValue::String(value))) = arg.0 {
154-
Ok(value)
155-
} else {
156-
Err(self.arg_type_err(arg.1, arg.2, index, "String"))
160+
macro_rules! impl_get_arg {
161+
($ty:ty, $pat:pat => $val:expr, $expected:literal) => {
162+
impl<'src> GetArg<'src, $ty> for FuncContext<'src> {
163+
fn get(&mut self, index: usize) -> Result<$ty, Rich<'src, char>> {
164+
let arg = self.get_arg(index)?;
165+
Ok(match arg.0 {
166+
$pat => $val,
167+
_ => return Err(self.arg_type_err(arg.1, arg.2, index, $expected)),
168+
})
169+
}
157170
}
158-
}
171+
};
159172
}
160173

161-
impl<'src> GetArg<'src, Vec<Expr>> for FuncContext<'src> {
162-
fn get(&mut self, index: usize) -> Result<Vec<Expr>, Rich<'src, char>> {
163-
let arg = self.get_arg(index)?;
164-
if let FuncArgument::Array(arr) = arg.0 {
165-
Ok(arr)
166-
} else {
167-
dbg!(&arg.0);
168-
Err(self.arg_type_err(arg.1, arg.2, index, "[Array]"))
169-
}
170-
}
171-
}
174+
impl_get_arg!(Box<Expr>, FuncArgument::Expression(v) => Box::new(v), "Expression");
175+
impl_get_arg!(
176+
String,
177+
FuncArgument::Expression(Expr::Literal(ExprValue::String(v))) => v,
178+
"String"
179+
);
180+
impl_get_arg!(Vec<Expr>, FuncArgument::Array(v) => v, "[Array]");
172181

173182
#[derive(Debug)]
174183
enum FuncArgument {
@@ -220,8 +229,13 @@ fn func_call<'src>(
220229
let res = match func_name {
221230
"any" => c.args1(Expr::Any),
222231
"all" => c.args1(Expr::All),
223-
"zoom" => Ok(Expr::Zoom),
232+
"not" => c.args1(Expr::Not),
233+
224234
"get" => c.args1(Expr::Get),
235+
"in" => c.args2(|needle, haystack| Expr::In { needle, haystack }),
236+
237+
"geom_type" => Ok(Expr::GeomType),
238+
"zoom" => Ok(Expr::Zoom),
225239
_ => c.unknown(),
226240
}
227241
.and_then(|r| {
@@ -398,7 +412,7 @@ mod tests {
398412
}
399413

400414
#[test]
401-
fn parse_literals() {
415+
fn parse_atoms() {
402416
let cases = [
403417
("42", 42.0.into()),
404418
("42.", 42.0.into()),
@@ -451,6 +465,24 @@ mod tests {
451465
Expr::Get("bool_prop".to_owned()),
452466
]),
453467
),
468+
("not(true)", Expr::Not(Box::new(true.into()))),
469+
(
470+
"not(not(bool_prop))",
471+
Expr::Not(Box::new(Expr::Not(Box::new(Expr::Get(
472+
"bool_prop".to_string(),
473+
))))),
474+
),
475+
(
476+
"in(param, ['candidate1', 'candidate2'])",
477+
Expr::In {
478+
needle: Box::new(Expr::Get("param".to_owned())),
479+
haystack: vec![
480+
"candidate1".to_owned().into(),
481+
"candidate2".to_owned().into(),
482+
],
483+
},
484+
),
485+
("geom_type()", Expr::GeomType),
454486
];
455487

456488
for (case, expected) in cases {
@@ -547,4 +579,14 @@ mod tests {
547579
fn parser_error_invalid_argument_type_array() {
548580
ass!(s("any(true)"), @r#""expected `[Array]` argument at position `1` of function `any`, but got `true` at 4..8""#);
549581
}
582+
583+
#[test]
584+
fn parser_error_unclosed_bracket() {
585+
ass!(s("zoom("), @r#""found end of input at 5..5 expected ''['', ''('', expression block, literal, any, property name, or '')''""#);
586+
}
587+
588+
#[test]
589+
fn parser_error_unclosed_array() {
590+
ass!(s("any([true, false)"), @r#""found '')'' at 16..17 expected ==, !=, >, >=, <, <=, '','', or '']''""#);
591+
}
550592
}

0 commit comments

Comments
 (0)