Skip to content

Instantly share code, notes, and snippets.

@benbenbenbenbenben
Created December 15, 2015 14:21
Show Gist options
  • Save benbenbenbenbenben/ab156ac2504cc55c7699 to your computer and use it in GitHub Desktop.
Save benbenbenbenbenben/ab156ac2504cc55c7699 to your computer and use it in GitHub Desktop.
/* lexical grammar */
%lex
%options case-insensitive
%%
\s+ /* skip whitespace */
\'[^']+\' return 'SQTERM'
\"[^"]+\" return 'DQTERM'
"and" return 'AND'
"or" return 'OR'
"," return ','
"not" return 'NOT'
^[^'",\(\)]+ return 'TERM'
"(" return '('
")" return ')'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
/* operator associations and precedence */
%left 'AND' 'OR' ','
%left 'NOT'
%start query
%% /* language grammar */
query
: expr EOF
{ /*typeof console !== 'undefined' ? console.log($1) : print($1);*/
return $1; }
;
args
: expr
{$$ = [$1]; }
| expr ',' expr
{$$ = Array.prototype.concat($1, $3); }
;
func
: TERM '(' ')'
{$$ = (function(f){ var c = f;
console.warn('[andOrIn]: no function like "' + c + '()", using text search');
return function(k) { return k.indexOf(c) > -1; }; })($1); }
| TERM '(' args ')'
{$$ = (function(f,a){ var c = f, p = a;
return c == 'in' ? function(k) { while(p.length > 0) if(p.shift()(k)) return true; return false; }
: c == 'match' ?
p.length < 1 ? (function() { console.warn('[andOrIn]: no function like "' + c + '()", using text search'); return function(k) { return k.indexOf(c) > -1; }; })()
: function(k) {
var func = p[0]; // function(string):int
var h = {
indexOf: function(pattern) {
// sanitize and replace * with .*, spaces with 1 or more spaces
pattern = pattern.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
pattern = pattern.replace(/\\\*/,'[^\\s]*');
pattern = pattern.replace(/\s+/, '\\s+');
var match = RegExp(pattern).exec(k);
return match ? match.index : -1;
}
};
return func(h);
}
: function(k) { return k.indexOf(c) > -1; }
})($1, $3); }
;
expr
: func
{$$ = (function(a){ var x = a; return function(k) { return x(k); }; })($1); }
| expr 'AND' expr
{$$ = (function(a,b){ var x = a, y = b; return function(k) { return x(k) && y(k); }; })($1, $3); }
| expr 'OR' expr
{$$ = (function(a,b){ var x = a, y = b; return function(k) { return x(k) || y(k); }; })($1, $3); }
| 'NOT' expr
{$$ = (function(a){ var x = a; return function(k) { return !x(k); }; })($2); }
| '(' expr ')'
{$$ = (function(a){ var x = a; return function(k) { return x(k); }; })($2); }
| SQTERM
{$$ = (function(a){ var q = a; return function(k) { return k.indexOf(q) > -1; }; })(yytext.replace(/^'|'$/g,'')); }
| DQTERM
{$$ = (function(a){ var q = a; return function(k) { return k.indexOf(q) > -1; }; })(yytext.replace(/^"|"$/g,'')); }
| TERM
{$$ = (function(a){ var q = a; return function(k) { return k.indexOf(q) > -1; }; })(yytext); }
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment