@emartech/data-aggregator-language
Advanced tools
Comparing version 2.4.0 to 2.4.1
@@ -14,18 +14,18 @@ { | ||
"dependencies": { | ||
"chevrotain": "3.7.2", | ||
"lodash": "4.17.10" | ||
"chevrotain": "4.1.0", | ||
"lodash": "4.17.11" | ||
}, | ||
"devDependencies": { | ||
"chai": "4.1.2", | ||
"eslint": "5.1.0", | ||
"chai": "4.2.0", | ||
"eslint": "5.7.0", | ||
"eslint-config-emarsys": "5.1.0", | ||
"eslint-plugin-require-path-exists": "1.1.7", | ||
"eslint-plugin-require-path-exists": "1.1.9", | ||
"mocha": "5.2.0", | ||
"semantic-release": "^15.8.1" | ||
"semantic-release": "15.10.3" | ||
}, | ||
"engines": { | ||
"node": "8.11.3", | ||
"npm": "6.2.0" | ||
"node": "8.12.0", | ||
"npm": "6.4.1" | ||
}, | ||
"version": "2.4.0" | ||
"version": "2.4.1" | ||
} |
@@ -39,3 +39,5 @@ # Data Aggregator Language | ||
### Constants | ||
### Number Results | ||
#### Constants | ||
* LENGTH | ||
@@ -47,3 +49,3 @@ * `LENGTH` (yields 2) | ||
### Unary Operators | ||
#### Unary Operators | ||
* SUM | ||
@@ -56,11 +58,19 @@ * `SUM reservations.silver` (yields 15) | ||
### Binary Operators | ||
#### Binary Operators | ||
+, -, *, / | ||
For example, `(LAST reservations.silver + 3) * 2 / 2` (yields 6) | ||
### Set Operators | ||
Set Operators may not be mixed with any of the other operators. | ||
### Array Results | ||
* UNION | ||
* `UNION customers` (yields ['brad', 'angelina']) | ||
### Boolean Results | ||
* EMPTY | ||
* `EMPTY UNION customers` (yields false) | ||
* NOT | ||
* `NOT EMPTY UNION customers` (yields true) | ||
## Using with Webpack | ||
@@ -67,0 +77,0 @@ Because of the [way the underlying Chevrotain library is implemented](https://github.com/SAP/chevrotain/blob/master/examples/parser/minification/README.md), name mangling |
@@ -25,12 +25,10 @@ 'use strict'; | ||
(() => { | ||
const lexer = new Lexer(tokens); | ||
const parser = new AggregatorParser([]); | ||
const AggregatorInterpreter = interpreterFactory(parser); | ||
const interpreter = new AggregatorInterpreter(); | ||
const lexer = new Lexer(tokens); | ||
const parser = new AggregatorParser(); | ||
const AggregatorInterpreter = interpreterFactory(parser); | ||
const interpreter = new AggregatorInterpreter(); | ||
module.exports = (input) => { | ||
interpreter.period = input; | ||
return createAggregator(lexer, parser, interpreter); | ||
}; | ||
})(); | ||
module.exports = (input) => { | ||
interpreter.period = input; | ||
return createAggregator(lexer, parser, interpreter); | ||
}; |
@@ -23,116 +23,117 @@ 'use strict'; | ||
describe('Binary Operands', () => { | ||
it('has a last operator', () => { | ||
expect(aggregate('LAST campaigns.email.open')).to.eql(4); | ||
}); | ||
describe('Number Expressions', () => { | ||
describe('Binary Operands', () => { | ||
it('has a last operator', () => { | ||
expect(aggregate('LAST campaigns.email.open')).to.eql(4); | ||
}); | ||
it('has a sum operator', () => { | ||
expect(aggregate('SUM campaigns.email.open')).to.eql(7); | ||
}); | ||
it('has a sum operator', () => { | ||
expect(aggregate('SUM campaigns.email.open')).to.eql(7); | ||
}); | ||
it('has an average operator', () => { | ||
expect(aggregate('AVERAGE campaigns.email.open')).to.eql(3.5); | ||
}); | ||
it('has an average operator', () => { | ||
expect(aggregate('AVERAGE campaigns.email.open')).to.eql(3.5); | ||
}); | ||
it('has a LENGTH constant', () => { | ||
expect(aggregate('LENGTH')).to.eql(2); | ||
}); | ||
it('has a rule for number literals', () => { | ||
expect(aggregate('1')).to.eql(1); | ||
}); | ||
it('works for floating point numbers', () => { | ||
expect(aggregate('0.5')).to.eql(0.5); | ||
}); | ||
}); | ||
describe('Binary Operators', () => { | ||
describe('Plus Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('SUM campaigns.email.open + LAST campaigns.email.open')).to.eql((3 + 4) + 4); | ||
it('has a LENGTH constant', () => { | ||
expect(aggregate('LENGTH')).to.eql(2); | ||
}); | ||
it('can take any binary operand', () => { | ||
expect(aggregate('SUM campaigns.email.open + 1')).to.eql((3 + 4) + 1); | ||
it('has a rule for number literals', () => { | ||
expect(aggregate('1')).to.eql(1); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('1 + 1 + 1')).to.eql(3); | ||
it('works for floating point numbers', () => { | ||
expect(aggregate('0.5')).to.eql(0.5); | ||
}); | ||
}); | ||
describe('Minus Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('SUM campaigns.email.open - LAST campaigns.email.open')).to.eql(3 + 4 - 4); | ||
}); | ||
describe('Binary Operators', () => { | ||
describe('Plus Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('SUM campaigns.email.open + LAST campaigns.email.open')).to.eql((3 + 4) + 4); | ||
}); | ||
it('can take any binary operand', () => { | ||
expect(aggregate('SUM campaigns.email.open + 1')).to.eql((3 + 4) + 1); | ||
}); | ||
it('can take any binary operand', () => { | ||
expect(aggregate('LAST campaigns.email.open + 1 - LAST campaigns.email.open')).to.eql(1); | ||
it('chains', () => { | ||
expect(aggregate('1 + 1 + 1')).to.eql(3); | ||
}); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('1 - 1 + 1 - 1')).to.eql(0); | ||
}); | ||
}); | ||
describe('Minus Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('SUM campaigns.email.open - LAST campaigns.email.open')).to.eql(3 + 4 - 4); | ||
}); | ||
describe('Multiplication Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('2 * 3')).to.eql(6); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('2 * 2 * 2 * 2')).to.eql(16); | ||
}); | ||
it('can take any binary operand', () => { | ||
expect(aggregate('LAST campaigns.email.open + 1 - LAST campaigns.email.open')).to.eql(1); | ||
}); | ||
it('has a higher precedence than the plus operator', () => { | ||
expect(aggregate('2 + 3 * 3')).to.eql(11); | ||
it('chains', () => { | ||
expect(aggregate('1 - 1 + 1 - 1')).to.eql(0); | ||
}); | ||
}); | ||
it('has a higher precedence than the minus operator', () => { | ||
expect(aggregate('10 - 3 * 2')).to.eql(4); | ||
}); | ||
}); | ||
describe('Multiplication Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('2 * 3')).to.eql(6); | ||
}); | ||
describe('Division Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('2 / 2')).to.eql(1); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('2 * 2 * 2 * 2')).to.eql(16); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('20 / 2 / 5')).to.eql(2); | ||
}); | ||
it('has a higher precedence than the plus operator', () => { | ||
expect(aggregate('2 + 3 * 3')).to.eql(11); | ||
}); | ||
it('doesnt matter how its precedence relates to the multiplication operator', () => { | ||
expect(aggregate('5 * 6 / 3')).to.eql(10); | ||
it('has a higher precedence than the minus operator', () => { | ||
expect(aggregate('10 - 3 * 2')).to.eql(4); | ||
}); | ||
}); | ||
it('has a higher precedence than the plus operator', () => { | ||
expect(aggregate('2 + 3 / 3')).to.eql(3); | ||
}); | ||
describe('Division Operator', () => { | ||
it('exists', () => { | ||
expect(aggregate('2 / 2')).to.eql(1); | ||
}); | ||
it('has a higher precedence than the minus operator', () => { | ||
expect(aggregate('9 - 3 / 3')).to.eql(8); | ||
}); | ||
it('chains', () => { | ||
expect(aggregate('20 / 2 / 5')).to.eql(2); | ||
}); | ||
it('yields accurate floating point results for all-number expressions', () => { | ||
expect(aggregate('5 / 2')).to.eql(2.5); | ||
}); | ||
it('doesnt matter how its precedence relates to the multiplication operator', () => { | ||
expect(aggregate('5 * 6 / 3')).to.eql(10); | ||
}); | ||
it('yields accurate floating point results when an operand is an aggregation expression', () => { | ||
expect(aggregate('LAST campaigns.email.open / 8')).to.eql(0.5); | ||
it('has a higher precedence than the plus operator', () => { | ||
expect(aggregate('2 + 3 / 3')).to.eql(3); | ||
}); | ||
it('has a higher precedence than the minus operator', () => { | ||
expect(aggregate('9 - 3 / 3')).to.eql(8); | ||
}); | ||
it('yields accurate floating point results for all-number expressions', () => { | ||
expect(aggregate('5 / 2')).to.eql(2.5); | ||
}); | ||
it('yields accurate floating point results when an operand is an aggregation expression', () => { | ||
expect(aggregate('LAST campaigns.email.open / 8')).to.eql(0.5); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('parentheses', () => { | ||
it('overwrites operator precedence', () => { | ||
expect(aggregate('(10 + 5) * 3')).to.eql(45); | ||
}); | ||
describe('parentheses', () => { | ||
it('overwrites operator precedence', () => { | ||
expect(aggregate('(10 + 5) * 3')).to.eql(45); | ||
it('can be placed around any number expression', () => { | ||
expect(aggregate('(((123)))')).to.eql(123); | ||
}); | ||
}); | ||
it('can be placed around any number expression', () => { | ||
expect(aggregate('(((123)))')).to.eql(123); | ||
}); | ||
}); | ||
@@ -146,3 +147,3 @@ | ||
describe('Set Operators', () => { | ||
describe('Array Expressions', () => { | ||
describe('Union Operator', () => { | ||
@@ -153,3 +154,5 @@ it('exists', () => { | ||
}); | ||
}); | ||
describe('Logical Expressions', () => { | ||
describe('Empty Operator', () => { | ||
@@ -164,5 +167,3 @@ it('works for non-empty arrays', () => { | ||
}); | ||
}); | ||
describe('Logical Operators', () => { | ||
describe('Not Operator', function() { | ||
@@ -172,2 +173,6 @@ it('works', function() { | ||
}); | ||
it('works four double negatives', function() { | ||
expect(aggregate('NOT NOT EMPTY UNION programs.users')).to.eql(true); | ||
}); | ||
}); | ||
@@ -174,0 +179,0 @@ }); |
@@ -23,3 +23,3 @@ 'use strict'; | ||
setOperationExpression(ctx) { | ||
arrayExpression(ctx) { | ||
return this.visit(ctx.expression); | ||
@@ -32,8 +32,8 @@ } | ||
emptyExpression(ctx) { | ||
return this._isEmpty(this.visit(ctx.unionExpression)); | ||
notExpression(ctx) { | ||
return this._accumulateNot(ctx.notOperator, this.visit(ctx.emptyExpression)); | ||
} | ||
notExpression(ctx) { | ||
return !this.visit(ctx.emptyExpression); | ||
emptyExpression(ctx) { | ||
return this._isEmpty(this.visit(ctx.arrayExpression)); | ||
} | ||
@@ -97,2 +97,9 @@ | ||
_accumulateNot(operators, bool) { | ||
if (operators) { | ||
return operators.reduce(accumulator => !accumulator, bool); | ||
} | ||
return bool; | ||
} | ||
_accumulateRhs(rhs, init, accumulateOperation) { | ||
@@ -99,0 +106,0 @@ if (rhs) { |
@@ -29,4 +29,4 @@ 'use strict'; | ||
class AggregatorParser extends Parser { | ||
constructor(input) { | ||
super(input, tokens, { outputCst: true }); | ||
constructor() { | ||
super(tokens, { outputCst: true }); | ||
@@ -38,13 +38,10 @@ /* eslint-disable-next-line consistent-this */ | ||
$.OR([ | ||
{ ALT: () => $.SUBRULE($.additionExpression, { LABEL: 'expression' }) }, | ||
{ ALT: () => $.SUBRULE($.setOperationExpression, { LABEL: 'expression' }) } | ||
{ ALT: () => $.SUBRULE($.arrayExpression, { LABEL: 'expression' }) }, | ||
{ ALT: () => $.SUBRULE($.notExpression, { LABEL: 'expression' }) }, | ||
{ ALT: () => $.SUBRULE($.additionExpression, { LABEL: 'expression' }) } | ||
]); | ||
}); | ||
$.RULE('setOperationExpression', () => { | ||
$.OR([ | ||
{ ALT: () => $.SUBRULE($.unionExpression, { LABEL: 'expression' }) }, | ||
{ ALT: () => $.SUBRULE($.emptyExpression, { LABEL: 'expression' }) }, | ||
{ ALT: () => $.SUBRULE($.notExpression, { LABEL: 'expression' }) } | ||
]); | ||
$.RULE('arrayExpression', () => { | ||
$.SUBRULE($.unionExpression, { LABEL: 'expression' }); | ||
}); | ||
@@ -57,12 +54,14 @@ | ||
$.RULE('notExpression', () => { | ||
$.MANY(() => { | ||
$.CONSUME(notOperator); | ||
}); | ||
$.SUBRULE($.emptyExpression); | ||
}); | ||
$.RULE('emptyExpression', () => { | ||
$.CONSUME(emptyOperator); | ||
$.SUBRULE($.unionExpression); | ||
$.SUBRULE($.arrayExpression); | ||
}); | ||
$.RULE('notExpression', () => { | ||
$.CONSUME(notOperator); | ||
$.SUBRULE($.emptyExpression); | ||
}); | ||
$.RULE('additionExpression', () => { | ||
@@ -69,0 +68,0 @@ $.SUBRULE($.minusExpression, { LABEL: 'lhs' }); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25534
613
103
+ Addedchevrotain@4.1.0(transitive)
+ Addedlodash@4.17.11(transitive)
- Removedchevrotain@3.7.2(transitive)
- Removedlodash@4.17.10(transitive)
Updatedchevrotain@4.1.0
Updatedlodash@4.17.11