Skip to content

Commit

Permalink
Merge pull request #10 from msantos/grammar-extensions
Browse files Browse the repository at this point in the history
Grammar extensions
  • Loading branch information
joewalnes committed Mar 5, 2015
2 parents 80e8c12 + e446ae9 commit 3e85f75
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Values | Description
--- | ---
43, -1.234 | Numbers
"hello" | String
foo, a.b.c | External data variable defined by application (may be numbers or strings)
foo, a.b.c, 'foo-bar' | External data variable defined by application (may be numbers or strings)

Numeric arithmetic | Description
--- | ---
Expand All @@ -86,6 +86,7 @@ x < y | Less than
x <= y | Less than or equal to
x > y | Greater than
x >= y | Greater than or equal to
x ~= y | Regular expression match
x in (a, b, c) | Equivalent to (x == a or x == b or x == c)
x not in (a, b, c) | Equivalent to (x != a and x != b and x != c)

Expand Down
5 changes: 4 additions & 1 deletion filtrex.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function filtrexParser() {
['\\,', 'return ",";'],
['==', 'return "==";'],
['\\!=', 'return "!=";'],
['\\~=', 'return "~=";'],
['>=', 'return ">=";'],
['<=', 'return "<=";'],
['<', 'return "<";'],
Expand All @@ -103,6 +104,7 @@ function filtrexParser() {
['\\s+', ''], // skip whitespace
['[0-9]+(?:\\.[0-9]+)?\\b', 'return "NUMBER";'], // 212.321
['[a-zA-Z][\\.a-zA-Z0-9_]*', 'return "SYMBOL";'], // some.Symbol22
['\'(?:[^\'])*\'', 'yytext = yytext.substr(1, yyleng-2); return "SYMBOL";'], // 'some-symbol'
['"(?:[^"])*"', 'yytext = yytext.substr(1, yyleng-2); return "STRING";'], // "foo"

// End
Expand All @@ -119,7 +121,7 @@ function filtrexParser() {
['left', 'or'],
['left', 'and'],
['left', 'in'],
['left', '==', '!='],
['left', '==', '!=', '~='],
['left', '<', '<=', '>', '>='],
['left', '+', '-'],
['left', '*', '/', '%'],
Expand All @@ -145,6 +147,7 @@ function filtrexParser() {
['not e' , code(['Number(!', 2, ')'])],
['e == e' , code(['Number(', 1, '==', 3, ')'])],
['e != e' , code(['Number(', 1, '!=', 3, ')'])],
['e ~= e' , code(['RegExp(', 3, ').test(', 1, ')'])],
['e < e' , code(['Number(', 1, '<' , 3, ')'])],
['e <= e' , code(['Number(', 1, '<=', 3, ')'])],
['e > e' , code(['Number(', 1, '> ', 3, ')'])],
Expand Down
14 changes: 10 additions & 4 deletions src/filtrex.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,12 @@ function compileExpression(expression, extraFunctions /* optional */) {
tree.forEach(toJs);
js.push(';');

var func = new Function('functions', 'data', js.join(''));
function unknown(funcName) {
throw 'Unknown function: ' + funcName + '()';
}
var func = new Function('functions', 'data', 'unknown', js.join(''));
return function(data) {
return func(functions, data);
return func(functions, data, unknown);
};
}

Expand Down Expand Up @@ -86,6 +89,7 @@ function filtrexParser() {
['\\,', 'return ",";'],
['==', 'return "==";'],
['\\!=', 'return "!=";'],
['\\~=', 'return "~=";'],
['>=', 'return ">=";'],
['<=', 'return "<=";'],
['<', 'return "<";'],
Expand All @@ -100,6 +104,7 @@ function filtrexParser() {
['\\s+', ''], // skip whitespace
['[0-9]+(?:\\.[0-9]+)?\\b', 'return "NUMBER";'], // 212.321
['[a-zA-Z][\\.a-zA-Z0-9_]*', 'return "SYMBOL";'], // some.Symbol22
['\'(?:[^\'])*\'', 'yytext = yytext.substr(1, yyleng-2); return "SYMBOL";'], // 'some-symbol'
['"(?:[^"])*"', 'yytext = yytext.substr(1, yyleng-2); return "STRING";'], // "foo"

// End
Expand All @@ -116,7 +121,7 @@ function filtrexParser() {
['left', 'or'],
['left', 'and'],
['left', 'in'],
['left', '==', '!='],
['left', '==', '!=', '~='],
['left', '<', '<=', '>', '>='],
['left', '+', '-'],
['left', '*', '/', '%'],
Expand All @@ -142,6 +147,7 @@ function filtrexParser() {
['not e' , code(['Number(!', 2, ')'])],
['e == e' , code(['Number(', 1, '==', 3, ')'])],
['e != e' , code(['Number(', 1, '!=', 3, ')'])],
['e ~= e' , code(['RegExp(', 3, ').test(', 1, ')'])],
['e < e' , code(['Number(', 1, '<' , 3, ')'])],
['e <= e' , code(['Number(', 1, '<=', 3, ')'])],
['e > e' , code(['Number(', 1, '> ', 3, ')'])],
Expand All @@ -151,7 +157,7 @@ function filtrexParser() {
['NUMBER' , code([1])],
['STRING' , code(['"', 1, '"'])],
['SYMBOL' , code(['data["', 1, '"]'])],
['SYMBOL ( argsList )', code(['functions.', 1, '(', 3, ')'])],
['SYMBOL ( argsList )', code(['(functions.hasOwnProperty("', 1, '") ? functions.', 1, '(', 3, ') : unknown("', 1, '"))'])],
['e in ( inSet )', code([1, ' in (function(o) { ', 4, 'return o; })({})'])],
['e not in ( inSet )', code(['!(', 1, ' in (function(o) { ', 5, 'return o; })({}))'])],
],
Expand Down
10 changes: 10 additions & 0 deletions test/filtrex-test.html
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@
eq(1, compileExpression('foo not in ("aa", "bb")')({foo:'cc'}));
},

'regexp test': function() {
eq(1, compileExpression('foo ~= "^[hH]ello"')({foo:'hello'}));
eq(0, compileExpression('foo ~= "^[hH]ello"')({foo:'bye'}));
},

'a ? b : c': function() {
eq(4, compileExpression('1 > 2 ? 3 : 4')());
eq(3, compileExpression('1 < 2 ? 3 : 4')());
Expand All @@ -120,6 +125,11 @@
eq(123, compileExpression('order.gooandstuff')({'order.gooandstuff': 123}));
},

'quoted symbols': function() {
eq(123, compileExpression('\'hello-world-foo\'')({'hello-world-foo': 123}));
eq(123, compileExpression('\'order+goo*and#stuff\'')({'order+goo*and#stuff': 123}));
},

'custom functions': function() {
function triple(x) { return x * 3; };
eq(21, compileExpression('triple(v)', {triple:triple})({v:7}));
Expand Down

0 comments on commit 3e85f75

Please sign in to comment.