Skip to content

Commit bfc92f9

Browse files
authored
Merge pull request #104 from jmespath-community/jep/arithmetic-expressions
JEP-016 Arithmetic Expressions
2 parents c2d4e49 + c572771 commit bfc92f9

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed

GRAMMAR.ABNF

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,62 @@ minus = %x2D ; -
658658
plus = %x2B ; +
659659
zero = %x30 ; 0
660660

661+
expression =/ arithmetic-expression ;; ## Arithmetic Expressions
662+
663+
arithmetic-expression =/ "+" expression ; + %x43
664+
arithmetic-expression =/ ( "-" / "" ) expression ; - %x45 – %x2212
665+
666+
arithmetic-expression = expression "%" expression ; % %x37
667+
arithmetic-expression =/ expression ( "*" / "×" ) expression ; * %x42 ×  %xD7
668+
arithmetic-expression =/ expression "+" expression ; + %x43
669+
arithmetic-expression =/ expression ( "-" / "" ) expression ; - %x45 – %x2212
670+
arithmetic-expression =/ expression ( "/" / "÷" ) expression ; / %x47 ÷
671+
672+
;; An `arithmetic-expression` enables simple computations using the four basic operations,
673+
;; as well as the modulo and integer-division operations.
674+
;;
675+
;; To support arithmetic operations, the following operators are available:
676+
;;
677+
;; - `+` addition operator
678+
;; - `-` subtraction operator
679+
;; - `*` multiplication operator
680+
;; - `/` division operator
681+
;; - `%` modulo operator
682+
;; - `//` integer division operator
683+
;;
684+
;; Proper mathematical operators are also supported using the following UNICODE characters:
685+
;;
686+
;; - `–` (U+2212 MINUS SIGN)
687+
;; - `÷` (U+00F7 DIVISION SIGN)
688+
;; - `×` (U+00D7 MULTIPLY SIGN)
689+
;;
690+
;; Arithmetic operations adhere to the usual precedence rules, from lowest to highest:
691+
;;
692+
;; - `-` subtraction operator and `+` addition operator
693+
;; - `/` division, `*` multiplication, `%` modulo and `//` integer division operators
694+
;;
695+
;; In the absence of parentheses, operators of the same level of precedence are evaluated from left to right.
696+
;; Arithmetic operators have higher precedence than comparison operators and lower precedence than the `.` "dot" `sub-expression` token separator.
697+
;;
698+
;; ## Examples
699+
;;
700+
;; ```
701+
;; search(a + b, {"a": 1, "b": 2}) -> 3
702+
;; search(a - b, {"a": 1, "b": 2}) -> -1
703+
;; search(a * b, {"a": 2, "b": 4}) -> 8
704+
;; search(a / b, {"a": 2, "b": 3}) -> 0.666666666666667
705+
;; search(a % b, {"a": 10, "b": 3} -> 1
706+
;; search(a // b, {"a": 10, "b": 3} -> -3
707+
;; search(a.b + cd, {"a": {"b": 1}, "c": {"d": 2}}) -> 3
708+
;; ```
709+
;;
710+
;; Since `arithmetic-expression` is not valid on the right-hand-side of a `sub-expression`, a `pipe-expression` can be used instead:
711+
;;
712+
;; ```
713+
;; search({ab: a.b, cd: c.d} | ab + cd, {"a": {"b": 1}, "c": {"d": 2}}) -> 3
714+
;; ```
715+
;;
716+
661717
expression =/ root-node ;; ## Root Reference
662718

663719
root-node = "$"

grammar/arithmetic.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
test0:
2+
context:
3+
query: "`1` + `2`"
4+
returns: 3.0
5+
test1:
6+
context:
7+
query: "`1` − `2`"
8+
returns: -1.0
9+
test2:
10+
context:
11+
query: "`2` × `4`"
12+
returns: 8.0
13+
test3:
14+
context:
15+
query: "`2` ÷ `3`"
16+
returns: 0.666666666666667
17+
test4:
18+
context:
19+
query: "`10` % `3`"
20+
returns: 1.0
21+
test5:
22+
context:
23+
query: "`10` // `3`"
24+
returns: 3.0
25+
test6:
26+
context:
27+
query: "-`1` − +`2`"
28+
returns: -3.0
29+
test7:
30+
context:
31+
query: "`1` ÷ `0`"
32+
error: not-a-number

jep-016-arithmetic-expressions.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Arithmetic Expressions
2+
3+
|||
4+
|---|---
5+
| **JEP** | 16
6+
| **Author** | Maxime Labelle
7+
| **Created**| 01-August-2022
8+
| **SemVer** | MINOR
9+
| **Status** | Draft
10+
11+
## Abstract
12+
13+
This JEP proposes a new `arithmetic-expression` rule in the grammar to support simple arithmetic operations.
14+
15+
## Motivation
16+
17+
JMESPath supports querying JSON documents that may return numbers at various stages, but lacks the capability to operate on them using simple arithmetic operations. The only support for arithmetic is currently brought by the `sum()` function.
18+
19+
## Specification
20+
21+
To support arithmetic operations, we need to introduce the following operators:
22+
23+
- `+` addition operator
24+
- `-` subtraction operator
25+
- `*` multiplication operator
26+
- `/` division operator
27+
- `%` modulo operator
28+
- `//` integer division operator
29+
30+
Proper mathematical operators also exist in Unicode and SHOULD be supported:
31+
32+
- `` (U+2212 MINUS SIGN)
33+
- `÷` (U+00F7 DIVISION SIGN)
34+
- `×` (U+00D7 MULTIPLY SIGN)
35+
36+
### Syntax changes
37+
38+
In addition to the following grammar changes, we introduce the usual operator precedence, from lowest to highest:
39+
40+
- `-` subtraction operator and `+` addition operator
41+
- `/` division, `*` multiplication, `%` modulo and `//` integer division operators
42+
43+
In the absence of parentheses, operators of the same level of precedence are evaluated from left to right.
44+
45+
Arithmetic operators have higher precedence than comparison operators and lower precedence than the `.` "dot" `sub-expression` token separator.
46+
47+
```abnf
48+
expression =/ arithmetic-expression
49+
50+
arithmetic-expression =/ "+" expression ; + %x43
51+
arithmetic-expression =/ ( "-" / "–" ) expression ; - %x45 – %x2212
52+
53+
arithmetic-expression = expression "%" expression ; % %x37
54+
arithmetic-expression =/ expression ( "*" / "×" ) expression ; * %x42 ×  %xD7
55+
arithmetic-expression =/ expression "+" expression ; + %x43
56+
arithmetic-expression =/ expression ( "-" / "–" ) expression ; - %x45 – %x2212
57+
arithmetic-expression =/ expression ( "/" / "÷" ) expression ; / %x47 ÷ %xF7
58+
arithmetic-expression = expression "//" expression ; // %47 %47
59+
60+
```
61+
62+
## Examples
63+
64+
|Expression|Result
65+
|---|---
66+
|`` `1` + `2` ``| `3.0`
67+
|`` `1` – `2` ``| `-1.0`
68+
|`` `2` × `4` ``| `8.0`
69+
|`` `2` ÷ `3` ``| `0.666666666666667`
70+
|`` `10` % `3` ``| `1.0`
71+
|`` `10` // `3` ``| `3.0`
72+
|`` -`1` − +`2` ``| `-3.0`
73+
74+
Since `arithmetic-expression` is not valid on the right-hand-side of a `sub-expression`, a `pipe-expression` can be used instead:
75+
76+
|Given|Expression|Result
77+
|---|---|---
78+
|`{ "a": { "b": 1 }, "c": { "d": 2 } }`|`` { ab: a.b, cd: c.d } \| ab + cd ``| `3`
79+
80+
## Compliance Tests
81+
82+
An `arithmetic.json` file will be added to the compliance test suite.
83+
The test suite will add the following new error type:
84+
85+
- not-a-number
86+
87+
This error type would be raised at run time when dividing by zero or when overflow occurs, for instance.

0 commit comments

Comments
 (0)