Last active
August 29, 2015 14:08
-
-
Save kevinswiber/50d0169bd2eaed82e7e8 to your computer and use it in GitHub Desktop.
Generate Web version of CaQL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| number [+-]?[0-9]*\.?[0-9]+(?:[eE][-+]?[0-9]+)? | |
| name [A-Za-z0-9_-][\.A-Za-z0-9_-]* | |
| escaped_name \[(?:(?!\])[^\\]|\\.)*\] | |
| %options case-insensitive | |
| %x sel fltr asgn loc ordby | |
| %% | |
| <INITIAL,sel,fltr,asgn,loc,ordby>\s+ /* skip whitespace */ | |
| "select" { | |
| this.begin('sel'); | |
| return 'SELECT'; | |
| } | |
| <sel,fltr,loc,ordby>"," return ',' | |
| <sel>"*" return '*' | |
| <sel>"as" return 'AS' | |
| <INITIAL,sel>"where" { | |
| this.popState(); /* in: INITIAL */ | |
| this.begin('fltr'); | |
| return 'WHERE'; | |
| } | |
| <sel,fltr>"order by" { | |
| this.popState(); /* in: INITIAL */ | |
| this.begin('ordby'); | |
| return 'ORDERBY'; | |
| } | |
| <sel>{name} return 'NAME' | |
| <sel>{escaped_name} { | |
| yytext = yytext.slice(1, -1); | |
| return 'NAME'; | |
| } | |
| <fltr>"and" return 'AND' | |
| <fltr>"or" return 'OR' | |
| <fltr>"not" return 'NOT' | |
| <fltr>"&&" return 'AND' | |
| <fltr>"||" return 'OR' | |
| <sel,fltr,ordby><<EOF>> { | |
| this.popState(); /* in: INITIAL */ | |
| return 'EOF'; | |
| } | |
| <fltr>{name} { | |
| this.begin('asgn'); | |
| return 'NAME'; | |
| } | |
| <fltr>{escaped_name} { | |
| this.begin('asgn'); | |
| yytext = yytext.slice(1, -1); | |
| return 'NAME'; | |
| } | |
| <fltr>"(" return '(' | |
| <fltr>")" return ')' | |
| <asgn>"eq"|"gt"|"lt"|"gte"|"lte" return 'COMPARISON' | |
| <asgn>">="|"<=" { | |
| yytext = letterify(yytext); | |
| return 'COMPARISON'; | |
| } | |
| <asgn>"="|">"|"<" { | |
| yytext = letterify(yytext); | |
| return 'COMPARISON'; | |
| } | |
| <asgn>"not" return 'NOT' | |
| <asgn>"contains" return 'CONTAINS' | |
| <asgn>"like" return 'LIKE' | |
| <asgn>"within" { | |
| this.begin('loc'); | |
| return 'WITHIN'; | |
| } | |
| <asgn>(\@\w+) { | |
| this.popState(); /* in fltr */ | |
| return 'PARAM'; | |
| } | |
| <asgn>(["'])(?:(?!\1)[^\\]|\\.)*\1 { | |
| this.popState(); /* in: fltr */ | |
| return 'STRING'; | |
| } | |
| <asgn>{number} { | |
| this.popState(); /* in: fltr */ | |
| return 'NUMBER'; | |
| } | |
| <asgn>"true" { | |
| this.popState(); /* in fltr */ | |
| yytext = true; | |
| return 'TRUE'; | |
| } | |
| <asgn>"false" { | |
| this.popState(); /* in fltr */ | |
| yytext = false; | |
| return 'FALSE'; | |
| } | |
| <asgn>"null" { | |
| this.popState(); /* in fltr */ | |
| yytext = null; | |
| return 'NULL'; | |
| } | |
| <loc>{number} return 'NUMBER' | |
| <loc>"of" return 'OF' | |
| <loc>"and" { | |
| this.popState(); /* in: asgn */ | |
| this.popState(); /* in: fltr */ | |
| return 'AND'; | |
| } | |
| <loc>"or" { | |
| this.popState(); /* in: asgn */ | |
| this.popState(); /* in: fltr */ | |
| return 'OR'; | |
| } | |
| <loc>"order by" { | |
| this.popState(); /* in: asgn */ | |
| this.popState(); /* in: fltr */ | |
| this.begin('ordby'); | |
| return 'ORDERBY'; | |
| } | |
| <ordby>"ASC" return 'ASC' | |
| <ordby>"DESC" return 'DESC' | |
| <ordby>{name} return 'NAME' | |
| <ordby>{escaped_name} { | |
| yytext = yytext.slice(1, -1); | |
| return 'NAME'; | |
| } | |
| <INITIAL,loc><<EOF>> return 'EOF' | |
| %% | |
| function letterify(op) { | |
| switch(op) { | |
| case '=' : op = 'eq'; break; | |
| case '>' : op = 'gt'; break; | |
| case '<' : op = 'lt'; break; | |
| case '>=' : op = 'gte'; break; | |
| case '<=' : op = 'lte'; break; | |
| } | |
| return op; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| %left OR | |
| %left AND | |
| %left NOT | |
| %start root | |
| %% | |
| root | |
| : select_statement EOF | |
| { return $1; } | |
| ; | |
| select_statement | |
| : SELECT fields where_optional orderby_optional | |
| { $$ = new yy.SelectStatementNode($2, $3, $4); } | |
| | where_clause orderby_optional | |
| { $$ = new yy.SelectStatementNode(new yy.FieldListNode('*'), $1, $2); } | |
| ; | |
| fields | |
| : column_list | |
| | '*' | |
| { $$ = new yy.FieldListNode(new yy.ColumnNode('*')); } | |
| ; | |
| column_list | |
| : column_field | |
| { $$ = new yy.FieldListNode($1); } | |
| | column_list ',' column_field | |
| { $1.push($3); $$ = $1; } | |
| ; | |
| column_field | |
| : NAME | |
| { $$ = new yy.ColumnNode($1) } | |
| | NAME AS NAME | |
| { $$ = new yy.ColumnNode($1, $3) } | |
| ; | |
| column | |
| : NAME | |
| ; | |
| where_optional | |
| : /* empty */ | |
| | where_clause | |
| ; | |
| where_clause | |
| : WHERE filter | |
| { $$ = new yy.FilterNode($2); } | |
| ; | |
| conjunction | |
| : filter AND filter | |
| { $$ = new yy.ConjunctionNode($1, $3); } | |
| ; | |
| disjunction | |
| : filter OR filter | |
| { $$ = new yy.DisjunctionNode($1, $3); } | |
| ; | |
| filter | |
| : predicate | |
| | conjunction | |
| | disjunction | |
| | '(' filter ')' | |
| { $$ = $2 } | |
| ; | |
| predicate | |
| : comparison_predicate | |
| | contains_predicate | |
| | location_predicate | |
| | like_predicate | |
| ; | |
| comparison_predicate | |
| : column COMPARISON literal | |
| { $$ = new yy.ComparisonPredicateNode($1, $2, $3); } | |
| | NOT comparison_predicate | |
| { $$ = $2.negate(); } | |
| ; | |
| contains_predicate | |
| : column CONTAINS STRING | |
| { $$ = new yy.ContainsPredicateNode($1, $3); } | |
| | column CONTAINS PARAM | |
| { $$ = new yy.ContainsPredicateNode($1, $3); } | |
| | NOT contains_predicate | |
| { $$ = $2.negate(); } | |
| ; | |
| like_predicate | |
| : column LIKE STRING | |
| { $$ = new yy.LikePredicateNode($1, $3); } | |
| | column LIKE PARAM | |
| { $$ = new yy.LikePredicateNode($1, $3); } | |
| | column NOT LIKE STRING | |
| { $$ = new yy.LikePredicateNode($1, $4).negate(); } | |
| | column NOT LIKE PARAM | |
| { $$ = new yy.LikePredicateNode($1, $4).negate(); } | |
| ; | |
| location_predicate | |
| : column WITHIN location | |
| { $$ = new yy.LocationPredicateNode($1, $3); } | |
| | NOT location_predicate | |
| { $$ = $2.negate(); } | |
| ; | |
| location | |
| : NUMBER OF coordinates | |
| { $$ = new yy.LocationNode($1, $3); } | |
| ; | |
| coordinates | |
| : NUMBER ',' NUMBER | |
| { $$ = new yy.CoordinatesNode($1, $3); } | |
| ; | |
| orderby_optional | |
| : /* empty */ | |
| | orderby_clause | |
| ; | |
| orderby_clause | |
| : ORDERBY sort_list | |
| { $$ = new yy.OrderByNode($2); } | |
| ; | |
| sort_list | |
| : sort_expression | |
| { $$ = new yy.SortListNode($1); } | |
| | sort_list ',' sort_expression | |
| { $1.push($3); $$ = $1; } | |
| ; | |
| sort_expression | |
| : NAME direction | |
| { $$ = new yy.SortNode($1, $2); } | |
| ; | |
| direction | |
| : /* empty */ | |
| | ASC | |
| | DESC | |
| ; | |
| boolean | |
| : TRUE | |
| | FALSE | |
| ; | |
| literal | |
| : NUMBER | |
| | STRING | |
| | PARAM | |
| | boolean | |
| | NULL | |
| ; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var file = require('read-file'); | |
| var ebnfParser = require('ebnf-parser'); | |
| var lexParser = require('lex-parser'); | |
| var Generator = require('jison').Generator; | |
| var grammarFile = '../calypso.yy'; | |
| var lexFile = '../calypso.l'; | |
| var grammar = ebnfParser.parse(file.readFileSync(grammarFile)); | |
| grammar.lex = lexParser.parse(file.readFileSync(lexFile)); | |
| var opts = { | |
| moduleName: 'caql', | |
| moduleType: 'js' | |
| }; | |
| var generator = new Generator(grammar, opts); | |
| var parserSource = generator.generate(opts); | |
| process.stdout.write(parserSource); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Set: