Skip to content

Commit afa6b1b

Browse files
committed
chore: reverse the order of the operator list so it is from highest to lowest precedence
1 parent 60a6693 commit afa6b1b

File tree

5 files changed

+40
-34
lines changed

5 files changed

+40
-34
lines changed

README.md

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -209,16 +209,15 @@ When using multiple operators, they will be evaluated according to their precede
209209
filter(.age >= 18 and .age <= 65)
210210
```
211211

212-
The operators have the following precedence, from lowest to highest:
212+
The operators have the following precedence, from highest to lowest:
213213

214-
-
215-
- `or`
216-
- `and`
217-
- `==`, `!=`
218-
- `>`, `>=`, `<`, `<=`, `in`, `not in`
219-
- `+`, `-`
220-
- `*`, `/`, `%`
221214
- `^`
215+
- `*`, `/`, `%`
216+
- `+`, `-`
217+
- `>`, `>=`, `<`, `<=`, `in`, `not in`
218+
- `==`, `!=`
219+
- `and`
220+
- `or`
222221

223222
See section [Function reference](reference/functions.md) for a detailed overview of all available functions and operators.
224223

@@ -411,17 +410,17 @@ Here:
411410

412411
You can have a look at the source code of the functions in `/src/functions.ts` for more examples.
413412

414-
- `operators` is an optional array with maps of operators having the same precedence, ordered from lowest to highest precedence. The default array with operators is the following, with the precedence going from lowest to highest:
413+
- `operators` is an optional array with maps of operators having the same precedence, ordered from highest to lowest precedence. The default array with operators is the following, with the precedence going from lowest to highest:
415414

416415
```js
417416
const operators = [
418-
{ or: 'or' },
419-
{ and: 'and' },
420-
{ eq: '==', ne: '!=' },
421-
{ gt: '>', gte: '>=', lt: '<', lte: '<=', in: 'in', 'not in': 'not in' },
422-
{ add: '+', subtract: '-' },
417+
{ pow: '^' },
423418
{ multiply: '*', divide: '/', mod: '%' },
424-
{ pow: '^' }
419+
{ add: '+', subtract: '-' },
420+
{ gt: '>', gte: '>=', lt: '<', lte: '<=', in: 'in', 'not in': 'not in' },
421+
{ eq: '==', ne: '!=' },
422+
{ and: 'and' },
423+
{ or: 'or' }
425424
]
426425
```
427426

src/constants.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
// operator precedence from lowest to highest
2-
export const operators = [
3-
{ or: 'or' },
4-
{ and: 'and' },
5-
{ eq: '==', ne: '!=' },
6-
{ gt: '>', gte: '>=', lt: '<', lte: '<=', in: 'in', 'not in': 'not in' },
7-
{ add: '+', subtract: '-' },
1+
import type { JSONQueryOperatorGroup } from './types'
2+
3+
// operator precedence from highest to lowest
4+
export const operators: JSONQueryOperatorGroup[] = [
5+
{ pow: '^' },
86
{ multiply: '*', divide: '/', mod: '%' },
9-
{ pow: '^' }
7+
{ add: '+', subtract: '-' },
8+
{ gt: '>', gte: '>=', lt: '<', lte: '<=', in: 'in', 'not in': 'not in' },
9+
{ eq: '==', ne: '!=' },
10+
{ and: 'and' },
11+
{ or: 'or' }
1012
]
1113

1214
export const unquotedPropertyRegex = /^[a-zA-Z_$][a-zA-Z\d_$]*$/

src/parse.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
startsWithWhitespaceRegex
99
} from './constants'
1010
import { functions } from './functions'
11-
import type { JSONQuery, JSONQueryParseOptions } from './types'
11+
import type { JSONQuery, JSONQueryOperatorGroup, JSONQueryParseOptions } from './types'
1212

1313
/**
1414
* Parse a string containing a JSON Query into JSON.
@@ -31,7 +31,7 @@ export function parse(query: string, options?: JSONQueryParseOptions): JSONQuery
3131

3232
const parsePipe = () => {
3333
skipWhitespace()
34-
const first = parseOperator(0)
34+
const first = parseOperator(allOperators.length - 1)
3535
skipWhitespace()
3636

3737
if (query[i] === '|') {
@@ -41,7 +41,7 @@ export function parse(query: string, options?: JSONQueryParseOptions): JSONQuery
4141
i++
4242
skipWhitespace()
4343

44-
pipe.push(parseOperator(0))
44+
pipe.push(parseOperator(allOperators.length - 1))
4545
}
4646

4747
return ['pipe', ...pipe]
@@ -56,7 +56,7 @@ export function parse(query: string, options?: JSONQueryParseOptions): JSONQuery
5656
return parseParenthesis()
5757
}
5858

59-
let left = parseOperator(precedenceLevel + 1)
59+
let left = parseOperator(precedenceLevel - 1)
6060

6161
skipWhitespace()
6262

@@ -66,14 +66,14 @@ export function parse(query: string, options?: JSONQueryParseOptions): JSONQuery
6666
break
6767
}
6868

69-
const right = parseOperator(precedenceLevel + 1)
69+
const right = parseOperator(precedenceLevel - 1)
7070
left = [name, left, right]
7171
}
7272

7373
return left
7474
}
7575

76-
const parseOperatorName = (currentOperators: Record<string, string>): string | undefined => {
76+
const parseOperatorName = (currentOperators: JSONQueryOperatorGroup): string | undefined => {
7777
// we sort the operators from longest to shortest, so we first handle "<=" and next "<"
7878
const sortedOperatorNames = Object.keys(currentOperators).sort((a, b) => b.length - a.length)
7979

src/stringify.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ export const stringify = (query: JSONQuery, options?: JSONQueryStringifyOptions)
3636
const allOperators = options?.operators ?? operators
3737
const allOperatorsMap = Object.assign({}, ...allOperators)
3838

39-
const _stringify = (query: JSONQuery, indent: string, operatorPrecedence = 0) =>
39+
const _stringify = (
40+
query: JSONQuery,
41+
indent: string,
42+
operatorPrecedence = allOperators.length - 1
43+
) =>
4044
isArray(query)
4145
? stringifyFunction(query as JSONQueryFunction, indent, operatorPrecedence)
4246
: JSON.stringify(query) // value (string, number, boolean, null)
@@ -79,7 +83,7 @@ export const stringify = (query: JSONQuery, options?: JSONQueryStringifyOptions)
7983
const leftStr = _stringify(left, indent, precedence)
8084
const rightStr = _stringify(right, indent, precedence)
8185

82-
return parentPrecedence > precedence
86+
return parentPrecedence < precedence
8387
? `(${leftStr} ${op} ${rightStr})`
8488
: `${leftStr} ${op} ${rightStr}`
8589
}

src/types.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,26 @@ export type JSONQuery = JSONQueryFunction | JSONQueryPipe | JSONQueryObject | JS
77
export type JSONProperty = string
88
export type JSONPath = JSONProperty[]
99
export type JSONQueryProperty = ['get', path?: string | JSONPath]
10+
export type JSONQueryOperatorGroup = Record<string, string>
1011

1112
export interface JSONQueryOptions {
1213
functions?: FunctionBuildersMap
13-
operators?: Record<string, string>[]
14+
operators?: JSONQueryOperatorGroup[]
1415
}
1516

1617
export interface JSONQueryCompileOptions {
1718
functions?: FunctionBuildersMap
1819
}
1920

2021
export interface JSONQueryStringifyOptions {
21-
operators?: Record<string, string>[]
22+
operators?: JSONQueryOperatorGroup[]
2223
maxLineLength?: number
2324
indentation?: string
2425
}
2526

2627
export interface JSONQueryParseOptions {
2728
functions?: Record<string, boolean> | FunctionBuildersMap
28-
operators?: Record<string, string>[]
29+
operators?: JSONQueryOperatorGroup[]
2930
}
3031

3132
export type Fun = (data: unknown) => unknown

0 commit comments

Comments
 (0)