Skip to content

Commit 76329d6

Browse files
committed
Upgrade to jsonata 2.1.0
1 parent 5f04671 commit 76329d6

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

jsonata

Submodule jsonata updated 62 files

src/jsonata/functions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,13 @@ def pad(string: Optional[str], width: Optional[int], char: Optional[str]) -> Opt
441441
if char is None or not char:
442442
char = " "
443443

444+
# match JS: truncate width to integer
445+
if width is not None:
446+
try:
447+
width = int(width)
448+
except Exception:
449+
width = 0
450+
444451
if width < 0:
445452
result = Functions.left_pad(string, -width, char)
446453
else:

src/jsonata/parser.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,12 @@ def __init__(self):
529529
# if/then/else ternary operator ?:
530530
self.register(Parser.InfixTernaryOperator(self, tokenizer.Tokenizer.operators["?"]))
531531

532+
# coalescing operator ??
533+
self.register(Parser.InfixCoalesce(self, tokenizer.Tokenizer.operators["??"]))
534+
535+
# elvis/default operator ?:
536+
self.register(Parser.InfixDefault(self, tokenizer.Tokenizer.operators["?:"]))
537+
532538
# object transformer
533539
self.register(Parser.PrefixObjectTransformer(self))
534540

@@ -854,6 +860,43 @@ def led(self, left):
854860
self._else = self._outer_instance.expression(0)
855861
return self
856862

863+
class InfixCoalesce(Infix):
864+
_outer_instance: 'Parser'
865+
866+
def __init__(self, outer_instance, get):
867+
super().__init__(outer_instance, "??", get)
868+
self._outer_instance = outer_instance
869+
870+
def led(self, left):
871+
self.type = "condition"
872+
# condition becomes function exists(left)
873+
cond = Parser.Symbol(self._outer_instance)
874+
cond.type = "function"
875+
cond.value = "("
876+
proc = Parser.Symbol(self._outer_instance)
877+
proc.type = "variable"
878+
proc.value = "exists"
879+
cond.procedure = proc
880+
cond.arguments = [left]
881+
self.condition = cond
882+
self.then = left
883+
self._else = self._outer_instance.expression(0)
884+
return self
885+
886+
class InfixDefault(Infix):
887+
_outer_instance: 'Parser'
888+
889+
def __init__(self, outer_instance, get):
890+
super().__init__(outer_instance, "?:", get)
891+
self._outer_instance = outer_instance
892+
893+
def led(self, left):
894+
self.type = "condition"
895+
self.condition = left
896+
self.then = left
897+
self._else = self._outer_instance.expression(0)
898+
return self
899+
857900
class PrefixObjectTransformer(Prefix):
858901
_outer_instance: 'Parser'
859902

src/jsonata/tokenizer.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class Tokenizer:
6565
'<=': 40,
6666
'>=': 40,
6767
'~>': 40,
68+
'?:': 40,
69+
'??': 40,
6870
'and': 30,
6971
'or': 25,
7072
'in': 40,
@@ -216,6 +218,14 @@ def next(self, prefix: bool) -> Optional[Token]:
216218
# ~> chain function
217219
self.position += 2
218220
return self.create("operator", "~>")
221+
if current_char == '?' and have_more and self.path[self.position + 1] == ':':
222+
# ?: default / elvis operator
223+
self.position += 2
224+
return self.create("operator", "?:")
225+
if current_char == '?' and have_more and self.path[self.position + 1] == '?':
226+
# ?? coalescing operator
227+
self.position += 2
228+
return self.create("operator", "??")
219229
# test for single char operators
220230
if Tokenizer.operators.get(str(current_char)) is not None:
221231
self.position += 1

0 commit comments

Comments
 (0)