From 27500761d5aefdf930ae14784b73eb24237707a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com> Date: Tue, 1 Jul 2025 10:35:43 +0200 Subject: [PATCH] Allow negation directly after a binary operator. This should address https://github.com/01mf02/jaq/issues/294. --- jaq-core/src/load/lex.rs | 5 +++-- jaq-core/tests/tests.rs | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/jaq-core/src/load/lex.rs b/jaq-core/src/load/lex.rs index 0825f34a3..b0b20651a 100644 --- a/jaq-core/src/load/lex.rs +++ b/jaq-core/src/load/lex.rs @@ -291,7 +291,8 @@ impl<'a> Lexer<&'a str> { fn token(&mut self) -> Option> { self.space(); - let is_op = |c| "|=!<>+-*/%".contains(c); + let hd_op = |c| "|=!<>+-*/%".contains(c); + let tl_op = |c| hd_op(c) && c != '-'; let mut chars = self.i.chars(); let (s, tok) = match chars.next()? { @@ -299,7 +300,7 @@ impl<'a> Lexer<&'a str> { '$' => (self.consumed(1, Self::ident1), Tok::Var), '@' => (self.consumed(1, Self::ident1), Tok::Fmt), '0'..='9' => (self.consumed(1, Self::num), Tok::Num), - c if is_op(c) => (self.consumed(1, |lex| lex.trim(is_op)), Tok::Sym), + c if hd_op(c) => (self.consumed(1, |lex| lex.trim(tl_op)), Tok::Sym), '.' => match chars.next() { Some('.') => (self.take(2), Tok::Sym), Some('a'..='z' | 'A'..='Z' | '_') => (self.consumed(2, Self::ident0), Tok::Sym), diff --git a/jaq-core/tests/tests.rs b/jaq-core/tests/tests.rs index 2ce68c6db..f28a19873 100644 --- a/jaq-core/tests/tests.rs +++ b/jaq-core/tests/tests.rs @@ -141,6 +141,8 @@ yields!(atomic_opt, "def x: 0; try x? catch 1", 0); yields!(neg_arr_iter1, "[-[][]]", json!([])); yields!(neg_arr_iter2, "try (-[])[] catch 0", 0); +yields!(neg_after_bin, ".+=-1", -1); + yields!(interpolation, r#"1 | "yields \(.+1)!""#, "yields 2!"); // this diverges from jq, which yields ["2 2", "3 2", "2 4", "3 4"], // probably due to different order of evaluation addition