From 26d9699842a429731844c93cbcb485519bb2c526 Mon Sep 17 00:00:00 2001 From: Jeroen Op 't Eynde Date: Wed, 9 Aug 2023 13:09:43 +0200 Subject: [PATCH] fix: compare with 'in' operator (#15) * fix: compare with 'in' operator * fix: use field in object for loop * test: add examples from #13 as tests * test: update test case following suggestion in #13 --- grammar.js | 27 ++++--- test/corpus/fieldname.txt | 155 +++++++++++++++++++++++++++++++++++++ test/corpus/forloop.txt | 78 +++++++++++++++++++ test/corpus/inoperator.txt | 68 ++++++++++++++++ 4 files changed, 314 insertions(+), 14 deletions(-) create mode 100644 test/corpus/fieldname.txt create mode 100644 test/corpus/forloop.txt create mode 100644 test/corpus/inoperator.txt diff --git a/grammar.js b/grammar.js index 1069920940..4bf58f8b92 100644 --- a/grammar.js +++ b/grammar.js @@ -156,7 +156,7 @@ module.exports = grammar({ [PREC.multiplicative, choice("*", "/", "%")], [PREC.additive, choice("+", "-")], [PREC.bitshift, choice("<<", ">>")], - [PREC.comparison, choice("<", "<=", ">", ">=")], + [PREC.comparison, choice("<", "<=", ">", ">=", "in")], [PREC.equality, choice("==", "!=")], [PREC.bitand, "&"], [PREC.bitxor, "^"], @@ -210,7 +210,7 @@ module.exports = grammar({ // error expr expr_error: ($) => prec.right(seq("error", $.expr)), - _expr_super: ($) => seq($.expr, "in", $.super), + _expr_super: ($) => prec(PREC.comparison, seq($.expr, "in", $.super)), _parenthesis: ($) => seq("(", $.expr, ")"), @@ -218,18 +218,17 @@ module.exports = grammar({ choice( // seq($.member, repeat(seq(",", $.member)), optional(",")), commaSep1($.member, true), - seq( - repeat(seq($.objlocal, ",")), - "[", - $.expr, - "]", - ":", - $.expr, - repeat(seq(",", $.objlocal)), - optional(","), - $.forspec, - optional($.compspec), - ), + $._objforloop, + ), + + _objforloop: ($) => + seq( + repeat(seq($.objlocal, ",")), + $.field, + repeat(seq(",", $.objlocal)), + optional(","), + $.forspec, + optional($.compspec), ), member: ($) => diff --git a/test/corpus/fieldname.txt b/test/corpus/fieldname.txt new file mode 100644 index 0000000000..ef4a016a70 --- /dev/null +++ b/test/corpus/fieldname.txt @@ -0,0 +1,155 @@ +=============================== +Resolve expr in fieldname key 1 +=============================== + +local a = 'a'; +{ [a]: 'a' } + +--- + +(document + (expr + (local_bind + (local) + (bind + (id) + (expr + (string + (string_start) + (string_content) + (string_end)))) + (expr + (member + (field + (fieldname + (expr + (id))) + (expr + (string + (string_start) + (string_content) + (string_end))))))))) + +=============================== +Resolve expr in fieldname key 2 +=============================== + +local prefix = 'Happy Hour '; +{ + [prefix + 'Mimosa']: 'Champagne', +} + +--- + +(document + (expr + (local_bind + (local) + (bind + (id) + (expr + (string + (string_start) + (string_content) + (string_end)))) + (expr + (member + (field + (fieldname + (expr + (expr (id)) + (expr + (string + (string_start) + (string_content) + (string_end))))) + (expr + (string + (string_start) + (string_content) + (string_end))))))))) + +=============================== +Resolve expr in fieldname key 3 +=============================== + +local Margarita(salted) = { + [if salted then 'garnish']: 'Salt', + ingredients: [ + { kind: 'Tequila Blanco', qty: 2 }, + ], +}; +{ + Margarita: Margarita(true), + 'Margarita Unsalted': Margarita(false), +} + +--- + +(document + (expr + (local_bind + (local) + (bind + function: (id) + params: + (params + (param + identifier: (id))) + body: (expr + (member + (field + (fieldname + (expr + condition: (expr (id)) + consequence: + (expr + (string + (string_start) + (string_content) + (string_end))))) + (expr + (string + (string_start) + (string_content) + (string_end))))) + (member + (field + (fieldname (id)) + (expr + (expr + (member + (field + (fieldname (id)) + (expr + (string + (string_start) + (string_content) + (string_end))))) + (member + (field + (fieldname + (id)) + (expr + (number)))))))) + )) + (expr + (member + (field + (fieldname (id)) + (expr + (expr (id)) + (args + (expr (true)))))) + (member + (field + (fieldname + (string + (string_start) + (string_content) + (string_end))) + (expr + (expr (id)) + (args + (expr + (false)))))))))) diff --git a/test/corpus/forloop.txt b/test/corpus/forloop.txt new file mode 100644 index 0000000000..7623739f9f --- /dev/null +++ b/test/corpus/forloop.txt @@ -0,0 +1,78 @@ +====================== +For loop in array +====================== + +[ + i + for i in std.range(0,10) +] + +--- + +(document + (expr + (expr (id)) + (forspec + (id) + (expr (expr (expr (id)) (id)) + (args (expr (number)) (expr (number))))))) + +====================== +For loop in object +====================== + +{ + ['item' + i]: i + for i in std.range(0,10) +} + +--- + +(document + (expr + (field + (fieldname + (expr + (expr + (string + (string_start) + (string_content) + (string_end))) + (expr (id)))) + (expr (id))) + (forspec + (id) + (expr (expr (expr (id)) (id)) + (args (expr (number)) (expr (number))))))) + +================================ +For loop in object with function +================================ + +{ + ['item' + i](v): i + v + for i in std.range(0,10) +} + +--- + +(document + (expr + (field + (fieldname + (expr + (expr + (string + (string_start) + (string_content) + (string_end))) + (expr (id)))) + (params + (param (id))) + (expr + (expr (id)) + (expr (id)))) + (forspec + (id) + (expr (expr (expr (id)) (id)) + (args (expr (number)) (expr (number))))))) diff --git a/test/corpus/inoperator.txt b/test/corpus/inoperator.txt new file mode 100644 index 0000000000..7c9d7a061c --- /dev/null +++ b/test/corpus/inoperator.txt @@ -0,0 +1,68 @@ +====================== +In operator on object +====================== + +local obj = { a: null }; +'a' in obj + +--- + +(document + (expr + (local_bind + (local) + (bind + (id) + (expr + (member + (field + (fieldname + (id)) + (expr + (null)))))) + (expr + (expr + (string + (string_start) + (string_content) + (string_end))) + (expr + (id)))))) + +====================== +In operator on super +====================== + +local obj = { a: null }; +obj + { b: 'a' in super } + +--- + +(document + (expr + (local_bind + (local) + (bind + (id) + (expr + (member + (field + (fieldname + (id)) + (expr + (null)))))) + (expr + (expr + (id)) + (expr + (member + (field + (fieldname + (id)) + (expr + (expr + (string + (string_start) + (string_content) + (string_end))) + (super)))))))))