%{ #include "jqp.h" #include #define YY_CTX_LOCAL 1 #define YY_CTX_MEMBERS \ JQP_AUX *aux; struct _yycontext; static void _jqp_finish(struct _yycontext *yy); static void _jqp_debug(struct _yycontext *yy, const char *text); static void *_jqp_malloc(struct _yycontext *yy, size_t size); static void *_jqp_realloc(struct _yycontext *yy, void *ptr, size_t size); static JQPUNIT *_jqp_unit(struct _yycontext *yy); static void _jqp_op_negate(struct _yycontext *yy); static void _jqp_op_negate_reset(struct _yycontext *yy); static JQPUNIT *_jqp_string(struct _yycontext *yy, jqp_string_flavours_t flv, const char *text); static JQPUNIT *_jqp_unescaped_string(struct _yycontext *yy, jqp_string_flavours_t flv, const char *text); static JQPUNIT *_jqp_number(struct _yycontext *yy, jqp_int_flavours_t flv, const char *text); static JQPUNIT *_jqp_placeholder(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_unit_op(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_unit_join(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_expr(struct _yycontext *yy, JQPUNIT *left, JQPUNIT *op, JQPUNIT *right); static JQPUNIT *_jqp_node(struct _yycontext *yy, JQPUNIT *value); static JQPUNIT *_jqp_projection(struct _yycontext *yy, JQPUNIT *value, uint8_t flags); static void _jqp_set_skip(struct _yycontext *yy, JQPUNIT *unit); static void _jqp_set_limit(struct _yycontext *yy, JQPUNIT *unit); static void _jqp_add_orderby(struct _yycontext *yy, JQPUNIT *unit); static void _jqp_set_aggregate_count(struct _yycontext *yy); static void _jqp_set_noidx(struct _yycontext *yy); static void _jqp_set_inverse(struct _yycontext *yy); static JQPUNIT *_jqp_json_string(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_json_number(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_json_true_false_null(struct _yycontext *yy, const char *text); static JQPUNIT *_jqp_json_pair(struct _yycontext *yy, JQPUNIT *key, JQPUNIT *val); static JQPUNIT *_jqp_json_collect(struct _yycontext *yy, jbl_type_t type, JQPUNIT *until); static JQP_STACK *_jqp_push(struct _yycontext *yy); static void _jqp_unit_push(struct _yycontext *yy, JQPUNIT *unit); static JQPUNIT *_jqp_unit_pop(struct _yycontext *yy); static void _jqp_string_push(struct _yycontext *yy, char *str, bool dup); static char *_jqp_string_pop(struct _yycontext *yy); static JQPUNIT *_jqp_pop_filter_factor_chain(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_pop_expr_chain(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_pop_node_chain(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_pop_projfields_chain(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_pop_projection_nodes(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_pop_ordernodes(struct _yycontext *yy, JQPUNIT *until); static JQPUNIT *_jqp_push_joined_projection(struct _yycontext *yy, JQPUNIT *p); static JQPUNIT *_jqp_pop_joined_projections(struct _yycontext *yy, JQPUNIT *until); static void _jqp_set_filters_expr(struct _yycontext *yy, JQPUNIT *expr); static JQPUNIT *_jqp_create_filterexpr_pk(struct _yycontext *yy, JQPUNIT *argument); static void _jqp_set_apply(struct _yycontext *yy, JQPUNIT *unit); static void _jqp_set_apply_delete(struct _yycontext *yy); static void _jqp_set_apply_upsert(struct _yycontext *yy, JQPUNIT *unit); static void _jqp_set_projection(struct _yycontext *yy, JQPUNIT *unit); #define YYSTYPE JQPUNIT* #define YY_MALLOC(yy_, sz_) _jqp_malloc(yy_, sz_) #define YY_REALLOC(yy_, ptr_, sz_) _jqp_realloc(yy_, ptr_, sz_) #define YY_INPUT(yy_, buf_, result_, max_size_) \ { \ JQP_AUX *aux = (yy_)->aux; \ if (aux->rc || *(aux->buf + aux->pos) == '\0') { \ result_ = 0; \ } else { \ char ch = *(aux->buf + aux->pos++); \ result_ = 1; \ *(buf_)= ch; \ } \ } %} QUERY = s:QEXPR { _jqp_set_filters_expr(yy, s); } (_ '|' _ (a:APPLY { _jqp_set_apply(yy, a); } | "del" { _jqp_set_apply_delete(yy); } | u:UPSERT { _jqp_set_apply_upsert(yy, u); } ) )? (_ p:PROJECTION { _jqp_set_projection(yy, p); } )? (_ OPTS )? _ EOF { _jqp_finish(yy); } QEXPR = FILTEREXPR_PK | FILTEREXPR FILTEREXPR_PK = (a:FILTERANCHOR { _jqp_unit_push(yy, a); })? '/' _ '=' _ ( p:PLACEHOLDER | p:NUMPK | p:NUMPK_ARR ) { $$ = _jqp_create_filterexpr_pk(yy, p) } FILTERJOIN = (<("and" | "or")> (__ "not" { _jqp_op_negate(yy); })?) { $$ = _jqp_unit_join(yy, yytext); } APPLY = "apply" __ ( PLACEHOLDER | OBJJ | ARRJ ) UPSERT = "upsert" __ ( PLACEHOLDER | OBJJ | ARRJ ) PROJECTION = '|' _ (sn:PROJNODES { _jqp_unit_push(yy, sn); } (_ { _jqp_string_push(yy, yytext, true); } _ n:PROJNODES { _jqp_push_joined_projection(yy, n); } )*) { $$ = _jqp_pop_joined_projections(yy, sn); } OPTS = '|' _ OPT (__ OPT)* OPT = SKIP | LIMIT | ORDERBY | COUNT | NOIDX | INVERSE SKIP = "skip" __ ( { $$ = _jqp_number(yy, JQP_INT_SKIP, yytext); } | p:PLACEHOLDER { $$ = p; }) { _jqp_set_skip(yy, $$); } LIMIT = "limit" __ ( { $$ = _jqp_number(yy, JQP_INT_LIMIT, yytext); } | p:PLACEHOLDER { $$ = p; }) { _jqp_set_limit(yy, $$); } COUNT = "count" { _jqp_set_aggregate_count(yy); } NOIDX = "noidx" { _jqp_set_noidx(yy); } INVERSE = "inverse" { _jqp_set_inverse(yy); } ORDERBY = ("asc" | "desc" { _jqp_op_negate(yy); }) __ ( p:ORDERNODES | p:PLACEHOLDER ) { p->string.flavour |= (yy->aux->negate ? JQP_STR_NEGATE : 0); _jqp_op_negate_reset(yy); _jqp_add_orderby(yy, p); } ORDERNODES = sn:ORDERNODE { _jqp_unit_push(yy, sn); } (n:ORDERNODE { _jqp_unit_push(yy, n); })* { $$ = _jqp_pop_ordernodes(yy, sn) } ORDERNODE = '/' PROJPROP PROJNODES = (a:PROJALL { $$ = _jqp_projection(yy, a, 0); } | (sn:PROJNODE { _jqp_unit_push(yy, sn); } (n:PROJNODE { _jqp_unit_push(yy, n);})*) { $$ = _jqp_pop_projection_nodes(yy, sn); }) PROJALL = "all" { $$ = _jqp_string(yy, JQP_STR_PROJALIAS, "all"); } PROJNODE = '/' (PROJFIELDS | PROJPROP) PROJFIELDS = ('{' _ sp:PROJPROP { _jqp_unit_push(yy, sp); } (_ ',' _ p:PROJPROP { _jqp_unit_push(yy, p); } )* _ '}') { $$ = _jqp_pop_projfields_chain(yy, sp); } PROJPROP = STRN | PLACEHOLDER | PSTRP PROJOIN = ('+' | '-') PSTRP = { $$ = _jqp_string(yy, 0, yytext); } PCHP = '\\' '\\' | '\\' [bfnrt] | '\\' 'u' HEX HEX HEX HEX | !["/{},\t\n\r ] . FILTERFACTOR = (FILTER | '(' FILTEREXPR ')') FILTEREXPR = ff:FILTERFACTOR { _jqp_unit_push(yy, ff); } (__ j:FILTERJOIN { _jqp_unit_push(yy, j); } __ f:FILTERFACTOR { _jqp_unit_push(yy, f); })* { $$ = _jqp_pop_filter_factor_chain(yy, ff); } FILTER = ((a:FILTERANCHOR { _jqp_unit_push(yy, a); })? fn:NODE { _jqp_unit_push(yy, fn); } (n:NODE { _jqp_unit_push(yy, n); })*) { $$ = _jqp_pop_node_chain(yy, fn); } FILTERANCHOR = '@' <([a-zA-Z0-9_\-]+)> { $$ = _jqp_string(yy, JQP_STR_ANCHOR, yytext); } NODE = '/' (n:STRN | n:NEXPR | n:STRP) { $$ = _jqp_node(yy, n); } NEXPR = ('[' _ n:NEXPAIR { _jqp_unit_push(yy, n); } ( __ j:NEXJOIN { _jqp_unit_push(yy, j); } __ np:NEXPAIR { _jqp_unit_push(yy, np); })* _ ']') { $$ = _jqp_pop_expr_chain(yy, n); } NEXJOIN = (<("and" | "or")> (__ "not" { _jqp_op_negate(yy); })?) { $$ = _jqp_unit_join(yy, yytext); } NEXPAIR = (l:NEXLEFT _ o:NEXOP _ r:NEXRIGHT) { $$ = _jqp_expr(yy, l, o, r); } NEXLEFT = (DBLSTAR | STRSTAR | STRN | NEXPRLEFT | STRP) NEXPRLEFT = ('[' _ l:STRSTAR _ o:NEXOP _ r:NEXRIGHT _ ']') { $$ = _jqp_expr(yy, l, o, r); } NEXRIGHT = (PLACEHOLDER | VALJ | STRP) PLACEHOLDER = ':' <([a-zA-Z0-9]+ | '?')> { $$ = _jqp_placeholder(yy, yytext); } NEXOP = ("not" __ { _jqp_op_negate(yy); })? <("in" | "ni" | "re")> { $$ = _jqp_unit_op(yy, yytext); } | <(">=" | "gte")> { $$ = _jqp_unit_op(yy, yytext); } | <("<=" | "lte")> { $$ = _jqp_unit_op(yy, yytext); } | ('!' _ { _jqp_op_negate(yy); })? <('=' | "eq" | '~')> { $$ = _jqp_unit_op(yy, yytext); } | <('>' | "gt")> { $$ = _jqp_unit_op(yy, yytext); } | <('<' | "lt")> { $$ = _jqp_unit_op(yy, yytext); } | <('~')> { $$ = _jqp_unit_op(yy, yytext); } STRP = { $$ = _jqp_unescaped_string(yy, 0, yytext); } DBLSTAR = "**" { $$ = _jqp_unescaped_string(yy, JQP_STR_DBL_STAR, "**"); } STRSTAR = "*" { $$ = _jqp_unescaped_string(yy, JQP_STR_STAR, "*"); } STRN = '"' '"' { $$ = _jqp_unescaped_string(yy, JQP_STR_QUOTED, yytext); } OBJJ = (s:SOBJJ { _jqp_unit_push(yy, s); } _ (fp:PAIRJ { _jqp_unit_push(yy, fp); } (_ ',' _ p:PAIRJ { _jqp_unit_push(yy, p); })* )? _ '}') { $$ = _jqp_json_collect(yy, JBV_OBJECT, s); } ARRJ = (s:SARRJ { _jqp_unit_push(yy, s); } _ (fv:VALJ { _jqp_unit_push(yy, fv); } (_ ',' _ v:VALJ { _jqp_unit_push(yy, v); })* )? _ ']') { $$ = _jqp_json_collect(yy, JBV_ARRAY, s); } SOBJJ = '{' { $$ = _jqp_unit(yy); } SARRJ = '[' { $$ = _jqp_unit(yy); } PAIRJ = (s:STRJ _ ':' _ v:VALJ) { $$ = _jqp_json_pair(yy, s, v); } VALJ = STRJ | NUMJ | OBJJ | ARRJ | "true" { $$ = _jqp_json_true_false_null(yy, "true"); } | "false" { $$ = _jqp_json_true_false_null(yy, "false"); } | "null" { $$ = _jqp_json_true_false_null(yy, "null"); } STRJ = '"' <(CHJ*)> '"' { $$ = _jqp_json_string(yy, yytext); } HEX = [0-9A-Fa-f] CHJ = '\\' '"' | '\\' '\\' | '\\' [bfnrt] | '\\' 'u' HEX HEX HEX HEX | !'"' . CHP = '\\' '\\' | '\\' [bfnrt] | '\\' 'u' HEX HEX HEX HEX | ![/"[\]=> { $$ = _jqp_json_number(yy, yytext); } NUMPK = <(NUMI)> { $$ = _jqp_json_number(yy, yytext); } NUMPK_ARR = (s:SARRJ { _jqp_unit_push(yy, s); } _ (fv:NUMPK { _jqp_unit_push(yy, fv); } (_ ',' _ v:NUMPK { _jqp_unit_push(yy, v); })* )? _ ']') { $$ = _jqp_json_collect(yy, JBV_ARRAY, s); } NUMI = '0' | [1-9] [0-9]* NUMF = '.' [0-9]+ NUME = [eE] [+-]? [0-9]+ _ = SPACE* __ = SPACE+ SPACE = ' ' | '\t' | EOL EOL = ('\r\n' | '\n' | '\r') EOF = !. %% #include "./inc/jqpx.c"