Skip to content

Commit

Permalink
feat: add anyof noneof operators
Browse files Browse the repository at this point in the history
  • Loading branch information
koladilip committed May 25, 2024
1 parent f864b2f commit 7789cae
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 10 deletions.
14 changes: 13 additions & 1 deletion src/lexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,20 @@ export class JsonTemplateLexer {
return this.matchKeywordValue(Keyword.SUBSETOF);
}

matchAnyOf(): boolean {
return this.matchKeywordValue(Keyword.ANYOF);
}

matchNoneOf(): boolean {
return this.matchKeywordValue(Keyword.NONEOF);
}

matchIN(): boolean {
return this.matchKeywordValue(Keyword.IN) || this.matchKeywordValue(Keyword.NOT_IN);
return this.matchKeywordValue(Keyword.IN);
}

matchNotIN(): boolean {
return this.matchKeywordValue(Keyword.NOT_IN);
}

matchFunction(): boolean {
Expand Down
2 changes: 2 additions & 0 deletions src/operators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export const binaryOperators = {

subsetof: (val1, val2): string => `${val1}.every((el) => {return ${val2}.includes(el);})`,

anyof: (val1, val2): string => `${val1}.some((el) => {return ${val2}.includes(el);})`,

'+': (val1, val2): string => `${val1}+${val2}`,

'-': (val1, val2): string => `${val1}-${val2}`,
Expand Down
38 changes: 36 additions & 2 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,15 @@ export class JsonTemplateParser {
return expr;
}

private parseInExpr(expr: Expression): BinaryExpression {
this.lexer.ignoreTokens(1);
return {
type: SyntaxType.IN_EXPR,
op: Keyword.IN,
args: [expr, this.parseRelationalExpr()],
};
}

private parseRelationalExpr(): BinaryExpression | Expression {
const expr = this.parseNextExpr(OperatorType.RELATIONAL);

Expand All @@ -702,19 +711,44 @@ export class JsonTemplateParser {
this.lexer.match('>') ||
this.lexer.match('<=') ||
this.lexer.match('>=') ||
this.lexer.matchIN() ||
this.lexer.matchContains() ||
this.lexer.matchSize() ||
this.lexer.matchEmpty() ||
this.lexer.matchAnyOf() ||
this.lexer.matchSubsetOf()
) {
return {
type: this.lexer.matchIN() ? SyntaxType.IN_EXPR : SyntaxType.COMPARISON_EXPR,
type: SyntaxType.COMPARISON_EXPR,
op: this.lexer.value(),
args: [expr, this.parseRelationalExpr()],
};
}

if (this.lexer.matchIN()) {
return this.parseInExpr(expr);
}

if (this.lexer.matchNotIN()) {
return {
type: SyntaxType.UNARY_EXPR,
op: '!',
arg: this.parseInExpr(expr),
};
}

if (this.lexer.matchNoneOf()) {
this.lexer.ignoreTokens(1);
return {
type: SyntaxType.UNARY_EXPR,
op: '!',
arg: {
type: SyntaxType.COMPARISON_EXPR,
op: Keyword.ANYOF,
args: [expr, this.parseRelationalExpr()],
},
};
}

return expr;
}

Expand Down
9 changes: 2 additions & 7 deletions src/translator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -687,13 +687,8 @@ export class JsonTemplateTranslator {
code.push(this.translateExpr(expr.args[0], val1, ctx));
code.push(this.translateExpr(expr.args[1], val2, ctx));
code.push(`if(typeof ${val2} === 'object'){`);
if (expr.op === Keyword.IN) {
const inCode = `(Array.isArray(${val2}) ? ${val2}.includes(${val1}) : ${val1} in ${val2})`;
code.push(JsonTemplateTranslator.generateAssignmentCode(resultVar, inCode));
} else {
const notInCode = `(Array.isArray(${val2}) ? !${val2}.includes(${val1}) : !(${val1} in ${val2}))`;
code.push(JsonTemplateTranslator.generateAssignmentCode(resultVar, notInCode));
}
const inCode = `(Array.isArray(${val2}) ? ${val2}.includes(${val1}) : ${val1} in ${val2})`;
code.push(JsonTemplateTranslator.generateAssignmentCode(resultVar, inCode));
code.push('} else {');
code.push(JsonTemplateTranslator.generateAssignmentCode(resultVar, 'false'));
code.push('}');
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export enum Keyword {
NOT = 'not',
CONTAINS = 'contains',
SUBSETOF = 'subsetof',
ANYOF = 'anyof',
NONEOF = 'noneof',
EMPTY = 'empty',
SIZE = 'size',
RETURN = 'return',
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/comparisons/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export const data: Scenario[] = [
true,
true,
true,
true,
true,
],
},
];
2 changes: 2 additions & 0 deletions test/scenarios/comparisons/template.jt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@
[] subsetof ["a", "b", "c"],
"abc" =~ /a.*c/,
"AdC" =~ /a.*c/i,
["a", "b"] anyof ["a", "c"],
["c", "d"] noneof ["a", "b"]
]

0 comments on commit 7789cae

Please sign in to comment.