Skip to content

Commit c9e53ff

Browse files
authored
Merge pull request #1 from vepo/reimplement-grammar
Reimplement grammar
2 parents 52cce6e + b105a51 commit c9e53ff

29 files changed

+517
-419
lines changed

src/main/antlr4/dev/vepo/jsonata/functions/generated/JSONataGrammar.g4

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,74 @@
11
grammar JSONataGrammar;
22

3-
expressions: expression+ EOF;
3+
expressions: (expression+ | object) EOF;
44

5-
expressionGroup: expression+;
5+
object: OBJ_OPEN fieldList OBJ_CLOSE # objectBuilder
6+
;
67

78
expression:
8-
functionStatement # functionCall
9-
| DOT? fieldPath # queryPath
10-
| ROOT # rootPath
11-
| fieldPredicate # fieldPredicateArray
12-
| indexPredicate # indexPredicateArray
13-
| rangePredicate # rangePredicateArray
14-
| DOT? arrayConstructor # arrayConstructorMapping
15-
| ARRAY_CAST # transformerArrayCast
16-
| WILDCARD WILDCARD DOT fieldName DOT? # transformerDeepFindByField
17-
| (DOT WILDCARD | WILDCARD DOT) # transformerWildcard
18-
| stringConcat # transformerStringConcat
19-
| DOT? '(' expressionGroup ')' # innerExpression
20-
| booleanExpression # expressionBooleanSentence
21-
| booleanCompare # expressionBooleanPredicate
22-
| algebraicExpression # expressionAlgebraic
23-
| DOT objectExpression # objectMapper
24-
| objectExpression # objectBuilder
25-
| STRING # stringValue
26-
| NUMBER # numberValue
9+
functionStatement # functionCall
10+
| ROOT # rootPath
11+
| IDENTIFIER # identifier
12+
| '*' # fieldValues
13+
| DESCEND # allDescendantSearch
14+
| DOLLAR # contextReferece
15+
| ARR_OPEN expressionList ARR_CLOSE # arrayConstructor
16+
| expression DOT OBJ_OPEN fieldList OBJ_CLOSE # objectMapper
17+
| expression OBJ_OPEN fieldList OBJ_CLOSE # objectConstructor
18+
| expression DOT expression # path
19+
| expression ARR_OPEN ARR_CLOSE # toArray
20+
| expression ARR_OPEN NUMBER ARR_CLOSE # arrayIndexQuery
21+
| expression ARR_OPEN expression ARR_CLOSE # arrayQuery
22+
| expression rangePredicate # rangeQuery
23+
| expression op=('<' | '<=' | '>' | '>=' | '!=' | '=' | 'in') expression # booleanCompare
24+
| expression op=('and' | 'or') expression # booleanExpression
25+
| expression op=('+' | '-' | '*' | '/' | '%' | '^') expression # algebraicExpression
26+
| expression '?' expression (':' expression)? # inlineIfExpression
27+
| expression '&' expression # concatValues
28+
| '(' expression ')' # contextValue
29+
| STRING # stringValue
30+
| NUMBER # numberValue
31+
| FLOAT # floatValue
32+
| EXP_NUMBER # expNumberValue
33+
| BOOLEAN # booleanValue
2734
;
2835

29-
objectExpression:
30-
'{' fieldPathOrString ':' fieldPathOrString ARRAY_CAST? (
31-
',' fieldPathOrString ':' fieldPathOrString ARRAY_CAST?
32-
)* '}';
33-
fieldPathOrString: fieldPath | STRING | NUMBER | BOOLEAN | objectExpression;
34-
fieldName: IDENTIFIER | QUOTED_VALUE;
35-
fieldPath: fieldName (DOT fieldName)*;
3636
functionStatement: IDENTIFIER '(' parameterStatement (',' parameterStatement)* ')' ;
37-
parameterStatement: fieldPath | functionDeclaration;
37+
parameterStatement: expression | functionDeclaration;
3838
functionDeclaration:
39-
'function' '(' IDENTIFIER (',' IDENTIFIER)* ')' '{' expressionGroup '}' # functionDeclarationBuilder
39+
'function' '(' IDENTIFIER (',' IDENTIFIER)* ')' '{' expression+ '}' # functionDeclarationBuilder
4040
;
41-
fieldPredicate: '[' IDENTIFIER '=' STRING ']';
42-
rangePredicate: '[[' NUMBER '..' NUMBER ']]';
43-
indexPredicate: '[' NUMBER ']';
44-
arrayConstructor: '[' fieldPath (',' fieldPath)* ']';
45-
stringConcat: stringOrField ('&' stringOrField)+;
46-
stringOrField: fieldPath | STRING | NUMBER | BOOLEAN;
47-
48-
booleanCompare: op=('<' | '<=' | '>' | '>=' | '!=' | '=' | 'in') expressionGroup;
49-
booleanExpression: op=('and' | 'or') expressionGroup;
50-
51-
algebraicExpression: op=('+' | '-' | '*' | '/' | '%' | '^') expressionGroup;
52-
53-
// BOOLEAN_OPERATOR: ;
54-
ARRAY_CAST: '[]';
55-
WILDCARD: '*';
41+
expressionList: expression (',' expression)*;
42+
fieldList: expression ':' expOrObject (',' expression ':' expOrObject)*;
43+
expOrObject: expression | object;
5644

45+
rangePredicate: ARR_OPEN ARR_OPEN NUMBER '..' NUMBER ARR_CLOSE ARR_CLOSE;
5746
BOOLEAN: 'true' | 'false';
47+
ROOT : '$$' ;
48+
DOLLAR: '$';
49+
DESCEND: '**';
50+
ARR_OPEN: '[';
51+
ARR_CLOSE: ']';
52+
OBJ_OPEN: '{';
53+
OBJ_CLOSE: '}';
54+
55+
IDENTIFIER: [\p{L}_$] [\p{L}0-9_$]*
56+
| BACK_QUOTE ~[`]* BACK_QUOTE;
57+
fragment BACK_QUOTE : '`';
5858

59-
STRING:
59+
STRING:
6060
'\'' (ESC | ~['\\])* '\''
6161
| '"' (ESC | ~["\\])* '"'
6262
;
6363
64-
ROOT : '$' ;
6564
NUMBER: '-'? [0-9]+;
66-
IDENTIFIER: [$A-Za-z_][$A-Za-z_0-9]*;
67-
QUOTED_VALUE: '`' (~'`')* '`';
65+
FLOAT: '-'? [0-9]+ '.' [0-9]+;
66+
EXP_NUMBER: '-'? [0-9]+ [eE] '-'? [0-9]+;
6867
6968
70-
fragment ESC : '\\' (["'\\/bfnrt] | UNICODE) ;
71-
fragment UNICODE : ([\u0080-\uFFFF] | 'u' HEX HEX HEX HEX) ;
72-
fragment HEX : [0-9a-fA-F] ;
69+
fragment ESC : '\\' (["'\\/bfnrt] | UNICODE);
70+
fragment UNICODE : ([\u0080-\uFFFF] | 'u' HEX HEX HEX HEX);
71+
fragment HEX : [0-9a-fA-F];
7372

7473
DOT: '.';
7574

src/main/java/dev/vepo/jsonata/functions/AlgebraicJSONataFunction.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,18 @@
22

33
import static dev.vepo.jsonata.functions.json.JsonFactory.numberValue;
44

5-
import java.util.List;
65
import java.util.stream.IntStream;
76

87
import com.fasterxml.jackson.databind.JsonNode;
98

109
import dev.vepo.jsonata.functions.data.Data;
1110
import dev.vepo.jsonata.functions.data.GroupedData;
1211

13-
public record AlgebraicJSONataFunction(AlgebraicOperator operator, List<JSONataFunction> rightExpressions) implements JSONataFunction {
12+
public record AlgebraicJSONataFunction(JSONataFunction left, AlgebraicOperator operator, JSONataFunction right) implements JSONataFunction {
1413

1514
@Override
1615
public Data map(Data original, Data current) {
17-
var right = rightExpressions.stream()
18-
.reduce((f1, f2) -> (o, v) -> f2.map(o, f1.map(o, v)))
19-
.map(f -> f.map(original, original).toJson())
20-
.orElse(current.toJson());
21-
return execute(current.toJson(), right);
16+
return execute(left.map(original, current).toJson(), right.map(original, current).toJson());
2217
}
2318

2419
private Data execute(JsonNode left, JsonNode right) {

src/main/java/dev/vepo/jsonata/functions/ArrayConstructorJSONataFunction.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,22 @@
55

66
import java.util.ArrayList;
77
import java.util.List;
8-
import java.util.function.Function;
98

10-
import dev.vepo.jsonata.functions.data.GroupedData;
119
import dev.vepo.jsonata.functions.data.Data;
10+
import dev.vepo.jsonata.functions.data.GroupedData;
1211

13-
public record ArrayConstructorJSONataFunction(List<Function<Data, Data>> arrayBuilder) implements JSONataFunction {
12+
public record ArrayConstructorJSONataFunction(List<JSONataFunction> arrayBuilder) implements JSONataFunction {
1413

1514
@Override
1615
public Data map(Data original, Data current) {
1716
if (current.isArray() && arrayBuilder.size() == 1) {
1817
var elements = new ArrayList<Data>();
1918
for (int i = 0; i < current.length(); ++i) {
20-
elements.add(arrayBuilder.get(0).apply(current.at(i)));
19+
elements.add(arrayBuilder.get(0).map(original, current.at(i)));
2120
}
2221
return json2Value(new GroupedData(elements).toJson());
2322
} else {
24-
return json2Value(arrayNode(arrayBuilder.stream().map(fn -> fn.apply(current).toJson()).toList()));
23+
return json2Value(arrayNode(arrayBuilder.stream().map(fn -> fn.map(original, current).toJson()).toList()));
2524
}
2625
}
2726
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import java.util.ArrayList;
4+
5+
import dev.vepo.jsonata.functions.data.Data;
6+
import dev.vepo.jsonata.functions.data.GroupedData;
7+
8+
public record ArrayQueryJSONataFunction(JSONataFunction mapFunction, JSONataFunction filterFunction) implements JSONataFunction {
9+
10+
@Override
11+
public Data map(Data original, Data current) {
12+
var mapped = mapFunction.map(original, current);
13+
if (mapped.isArray() || mapped.isList()) {
14+
var filteredData = new ArrayList<Data>();
15+
for (int i = 0; i < mapped.length(); ++i) {
16+
var currData = mapped.at(i);
17+
var currResult = filterFunction.map(original, currData).toJson();
18+
if (currResult.isBoolean() && currResult.asBoolean()) {
19+
filteredData.add(mapped.at(i));
20+
}
21+
}
22+
return new GroupedData(filteredData);
23+
} else {
24+
return JSONataFunction.empty();
25+
}
26+
}
27+
28+
}

src/main/java/dev/vepo/jsonata/functions/BooleanCompareJSONataFunction.java

Lines changed: 0 additions & 30 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import static dev.vepo.jsonata.functions.json.JsonFactory.booleanValue;
4+
5+
import com.fasterxml.jackson.databind.JsonNode;
6+
7+
import dev.vepo.jsonata.functions.data.Data;
8+
9+
public record BooleanExpressionJSONataFunction(JSONataFunction left, BooleanOperator operator, JSONataFunction right) implements JSONataFunction {
10+
11+
@Override
12+
public Data map(Data original, Data current) {
13+
return booleanValue(compare(left.map(original, current).toJson(),
14+
right.map(original, current).toJson()));
15+
}
16+
17+
private boolean compare(JsonNode left, JsonNode right) {
18+
return switch (operator) {
19+
case AND -> left.asBoolean() && right.asBoolean();
20+
case OR -> left.asBoolean() || right.asBoolean();
21+
};
22+
}
23+
24+
}

src/main/java/dev/vepo/jsonata/functions/BuiltInSortJSONataFunction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
import dev.vepo.jsonata.functions.data.Data;
99
import dev.vepo.jsonata.functions.data.GroupedData;
1010

11-
public record BuiltInSortJSONataFunction(FieldPathJSONataFunction extractor, Optional<DeclaredFunction> function,
11+
public record BuiltInSortJSONataFunction(JSONataFunction extractor, Optional<DeclaredFunction> function,
1212
Comparator<Data> comparator)
1313
implements JSONataFunction {
14-
public BuiltInSortJSONataFunction(FieldPathJSONataFunction extractor, Optional<DeclaredFunction> function) {
14+
public BuiltInSortJSONataFunction(JSONataFunction extractor, Optional<DeclaredFunction> function) {
1515
this(extractor, function, buildComparator(function));
1616
}
1717

src/main/java/dev/vepo/jsonata/functions/BuiltInSumJSONataFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import dev.vepo.jsonata.functions.data.Data;
88
import dev.vepo.jsonata.functions.json.JsonFactory;
99

10-
public record BuiltInSumJSONataFunction(FieldPathJSONataFunction extractor) implements JSONataFunction {
10+
public record BuiltInSumJSONataFunction(JSONataFunction extractor) implements JSONataFunction {
1111

1212
@Override
1313
public Data map(Data original, Data current) {

src/main/java/dev/vepo/jsonata/functions/CompareValuesJSONataFunction.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@
33
import static dev.vepo.jsonata.functions.json.JsonFactory.booleanValue;
44
import static java.util.Spliterators.spliteratorUnknownSize;
55

6-
import java.util.List;
76
import java.util.stream.StreamSupport;
87

98
import com.fasterxml.jackson.databind.JsonNode;
109

1110
import dev.vepo.jsonata.functions.data.Data;
1211

13-
public record CompareValuesJSONataFunction(CompareOperator operator, List<JSONataFunction> rightExpressions) implements JSONataFunction {
12+
public record CompareValuesJSONataFunction(JSONataFunction left, CompareOperator operator, JSONataFunction right) implements JSONataFunction {
1413

1514
@Override
1615
public Data map(Data original, Data current) {
17-
return booleanValue(compare(current.toJson(),
18-
rightExpressions.stream()
19-
.reduce((f1, f2) -> (o, v) -> f2.map(o, f1.map(o, v)))
20-
.map(f -> f.map(original, original)
21-
.toJson())
22-
.orElse(current.toJson())));
16+
return booleanValue(compare(left.map(original, current).toJson(),
17+
right.map(original, original).toJson()));
2318
}
2419

2520
private boolean compare(JsonNode left, JsonNode right) {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package dev.vepo.jsonata.functions;
2+
3+
import static dev.vepo.jsonata.functions.json.JsonFactory.json2Value;
4+
5+
import dev.vepo.jsonata.functions.data.Data;
6+
7+
public record ContextValueJSONataFunction(JSONataFunction inner) implements JSONataFunction {
8+
9+
@Override
10+
public Data map(Data original, Data current) {
11+
return json2Value(inner.map(current, current).toJson());
12+
}
13+
}

0 commit comments

Comments
 (0)