UNPKG

odatafy-parser

Version:

generate odatafy ast from odata query parameters

1,294 lines 61.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const assert_1 = __importDefault(require("assert")); const filterParser_1 = __importDefault(require("../../../src/parsing/filterParser")); function testParsingAndAST(testcase) { it(`should parse ${testcase.type}: ${testcase.input}`, () => { let ast = filterParser_1.default.parse(testcase.input); assert_1.default.deepStrictEqual(ast, testcase.expectedAST); }); } //with pre and postproc describe('filter-expressions with logical operators', () => { describe('basic operator tests', () => { [{ type: "simple expression with and", input: "A eq 1 and B eq 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with or", input: "A eq 1 or B eq 2", expectedAST: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "expression with two ands", input: "A eq 1 and B eq 2 and C eq 3", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with two ors", input: "A eq 1 or B eq 2 or C eq 3", expectedAST: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with and + or", input: "A eq 1 and B eq 2 or C eq 3", expectedAST: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with or + and", input: "A eq 1 or B eq 2 and C eq 3", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }].forEach(testcase => testParsingAndAST(testcase)); }); describe('operator precedence tests (eq/ne/gt/lt/ge/le > not > and/or)', () => { [{ type: "simple expression with and / eq", input: "A eq 1 and B eq 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with and / ne", input: "A ne 1 and B ne 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "ne", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "ne", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with and / gt", input: "A gt 1 and B gt 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "gt", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "gt", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with and / lt", input: "A lt 1 and B lt 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "lt", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "lt", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with and / le", input: "A le 1 and B le 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "le", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "le", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "simple expression with and / ge", input: "A ge 1 and B ge 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "ge", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "ge", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "not in a comparison expression with eq", input: "not Name eq 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "eq", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in a comparison expression with ne", input: "not Name ne 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "ne", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in a comparison expression with lt", input: "not Name lt 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "lt", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in a comparison expression with gt", input: "not Name gt 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "gt", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in a comparison expression with le", input: "not Name le 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "le", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in a comparison expression with ge", input: "not Name ge 'Max'", expectedAST: { nodeType: 'OperatorNode', op: 'not', right: { left: { nodeType: "SymbolNode", type: "Identifier", value: 'Name' }, nodeType: "OperatorNode", op: "ge", right: { nodeType: "ConstantNode", type: "String", value: 'Max' } } } }, { type: "not in and expression on the left", input: "not A eq 1 and B eq 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "not", right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } }, { type: "not in and expression on the right", input: "A eq 1 and not B eq 2", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "not", right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } } } }, ].forEach(testcase => testParsingAndAST(testcase)); }); describe('expressions with grouping', () => { [{ type: "expression with or + and with grouping the first two no spaces", input: "(A eq 1 or B eq 2) and C eq 3", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with or + and with grouping the first two with spaces", input: "( A eq 1 or B eq 2 ) and C eq 3", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with or + and with grouping the last two no spaces", input: "A eq 1 or (B eq 2 and C eq 3)", expectedAST: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } } }, { type: "expression with or + and with grouping the last two with spaces", input: "A eq 1 or ( B eq 2 and C eq 3 )", expectedAST: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } } }, { type: "expression with or + and with nested grouping no spaces", input: "((A eq 1 or B eq 2) and C eq 3)", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with or + and with nested grouping with spaces", input: "( ( A eq 1 or B eq 2 ) and C eq 3 )", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } } } }, { type: "expression with two groupings no spaces", input: "(A eq 1 or B eq 2) and (C eq 3 or D eq 4)", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "D" }, right: { nodeType: "ConstantNode", type: "Integer", value: 4 } } } } }, { type: "expression with two groupings with spaces", input: "( A eq 1 or B eq 2 ) and ( C eq 3 or D eq 4 )", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "D" }, right: { nodeType: "ConstantNode", type: "Integer", value: 4 } } } } }, { type: "expression with two nested groupings no spaces", input: "((A eq 1 or B eq 2) and (C eq 3 or D eq 4))", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "B" }, right: { nodeType: "ConstantNode", type: "Integer", value: 2 } } }, right: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "C" }, right: { nodeType: "ConstantNode", type: "Integer", value: 3 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "D" }, right: { nodeType: "ConstantNode", type: "Integer", value: 4 } } } } }, { type: "expression with two nested groupings with spaces", input: "( ( A eq 1 or B eq 2 ) and ( C eq 3 or D eq 4 ) )", expectedAST: { nodeType: "OperatorNode", op: "and", left: { nodeType: "OperatorNode", op: "or", left: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "Identifier", value: "A" }, right: { nodeType: "ConstantNode", type: "Integer", value: 1 } }, right: { nodeType: "OperatorNode", op: "eq", left: { nodeType: "SymbolNode", type: "I