1%{ 2#include "jqp.h" 3#include "jbl.h" 4 5 6#define YY_CTX_LOCAL 1 7#define YY_CTX_MEMBERS \ 8 JQP_AUX *aux; 9 10struct _yycontext; 11 12static void _jqp_finish(struct _yycontext *yy); 13static void _jqp_debug(struct _yycontext *yy, const char *text); 14static void *_jqp_malloc(struct _yycontext *yy, size_t size); 15static void *_jqp_realloc(struct _yycontext *yy, void *ptr, size_t size); 16static JQPUNIT *_jqp_unit(struct _yycontext *yy); 17 18static void _jqp_op_negate(struct _yycontext *yy); 19static void _jqp_op_negate_reset(struct _yycontext *yy); 20 21static JQPUNIT *_jqp_string(struct _yycontext *yy, jqp_string_flavours_t flv, const char *text); 22static JQPUNIT *_jqp_unescaped_string(struct _yycontext *yy, jqp_string_flavours_t flv, const char *text); 23static JQPUNIT *_jqp_number(struct _yycontext *yy, jqp_int_flavours_t flv, const char *text); 24static JQPUNIT *_jqp_placeholder(struct _yycontext *yy, const char *text); 25static JQPUNIT *_jqp_unit_op(struct _yycontext *yy, const char *text); 26static JQPUNIT *_jqp_unit_join(struct _yycontext *yy, const char *text); 27static JQPUNIT *_jqp_expr(struct _yycontext *yy, JQPUNIT *left, JQPUNIT *op, JQPUNIT *right); 28static JQPUNIT *_jqp_node(struct _yycontext *yy, JQPUNIT *value); 29static JQPUNIT *_jqp_projection(struct _yycontext *yy, JQPUNIT *value, uint8_t flags); 30static void _jqp_set_skip(struct _yycontext *yy, JQPUNIT *unit); 31static void _jqp_set_limit(struct _yycontext *yy, JQPUNIT *unit); 32static void _jqp_add_orderby(struct _yycontext *yy, JQPUNIT *unit); 33static void _jqp_set_aggregate_count(struct _yycontext *yy); 34static void _jqp_set_noidx(struct _yycontext *yy); 35static void _jqp_set_inverse(struct _yycontext *yy); 36 37static JQPUNIT *_jqp_json_string(struct _yycontext *yy, const char *text); 38static JQPUNIT *_jqp_json_number(struct _yycontext *yy, const char *text); 39static JQPUNIT *_jqp_json_true_false_null(struct _yycontext *yy, const char *text); 40static JQPUNIT *_jqp_json_pair(struct _yycontext *yy, JQPUNIT *key, JQPUNIT *val); 41static JQPUNIT *_jqp_json_collect(struct _yycontext *yy, jbl_type_t type, JQPUNIT *until); 42 43static JQP_STACK *_jqp_push(struct _yycontext *yy); 44static void _jqp_unit_push(struct _yycontext *yy, JQPUNIT *unit); 45static JQPUNIT *_jqp_unit_pop(struct _yycontext *yy); 46static void _jqp_string_push(struct _yycontext *yy, char *str, bool dup); 47static char *_jqp_string_pop(struct _yycontext *yy); 48 49static JQPUNIT *_jqp_pop_filter_factor_chain(struct _yycontext *yy, JQPUNIT *until); 50static JQPUNIT *_jqp_pop_expr_chain(struct _yycontext *yy, JQPUNIT *until); 51static JQPUNIT *_jqp_pop_node_chain(struct _yycontext *yy, JQPUNIT *until); 52static JQPUNIT *_jqp_pop_projfields_chain(struct _yycontext *yy, JQPUNIT *until); 53static JQPUNIT *_jqp_pop_projection_nodes(struct _yycontext *yy, JQPUNIT *until); 54static JQPUNIT *_jqp_pop_ordernodes(struct _yycontext *yy, JQPUNIT *until); 55static JQPUNIT *_jqp_push_joined_projection(struct _yycontext *yy, JQPUNIT *p); 56static JQPUNIT *_jqp_pop_joined_projections(struct _yycontext *yy, JQPUNIT *until); 57 58static void _jqp_set_filters_expr(struct _yycontext *yy, JQPUNIT *expr); 59static JQPUNIT *_jqp_create_filterexpr_pk(struct _yycontext *yy, JQPUNIT *argument); 60static void _jqp_set_apply(struct _yycontext *yy, JQPUNIT *unit); 61static void _jqp_set_apply_delete(struct _yycontext *yy); 62static void _jqp_set_apply_upsert(struct _yycontext *yy, JQPUNIT *unit); 63static void _jqp_set_projection(struct _yycontext *yy, JQPUNIT *unit); 64 65#define YYSTYPE JQPUNIT* 66#define YY_MALLOC(yy_, sz_) _jqp_malloc(yy_, sz_) 67#define YY_REALLOC(yy_, ptr_, sz_) _jqp_realloc(yy_, ptr_, sz_) 68 69#define YY_INPUT(yy_, buf_, result_, max_size_) \ 70 { \ 71 JQP_AUX *aux = (yy_)->aux; \ 72 if (aux->rc || *(aux->buf + aux->pos) == '\0') { \ 73 result_ = 0; \ 74 } else { \ 75 char ch = *(aux->buf + aux->pos++); \ 76 result_ = 1; \ 77 *(buf_)= ch; \ 78 } \ 79 } 80%} 81 82QUERY = s:QEXPR { _jqp_set_filters_expr(yy, s); } 83 (_ '|' _ (a:APPLY { _jqp_set_apply(yy, a); } | "del" { _jqp_set_apply_delete(yy); } | u:UPSERT { _jqp_set_apply_upsert(yy, u); } ) )? 84 (_ p:PROJECTION { _jqp_set_projection(yy, p); } )? 85 (_ OPTS )? 86 _ EOF { _jqp_finish(yy); } 87 88QEXPR = FILTEREXPR_PK | FILTEREXPR 89 90FILTEREXPR_PK = (a:FILTERANCHOR { _jqp_unit_push(yy, a); })? 91 '/' _ '=' _ ( p:PLACEHOLDER | p:NUMPK | p:NUMPK_ARR ) 92 { $$ = _jqp_create_filterexpr_pk(yy, p) } 93 94FILTERJOIN = (<("and" | "or")> (__ "not" { _jqp_op_negate(yy); })?) { $$ = _jqp_unit_join(yy, yytext); } 95 96APPLY = "apply" __ ( PLACEHOLDER | OBJJ | ARRJ ) 97 98UPSERT = "upsert" __ ( PLACEHOLDER | OBJJ | ARRJ ) 99 100PROJECTION = '|' _ (sn:PROJNODES { _jqp_unit_push(yy, sn); } 101 (_ <PROJOIN> { _jqp_string_push(yy, yytext, true); } _ n:PROJNODES { _jqp_push_joined_projection(yy, n); } )*) 102 { $$ = _jqp_pop_joined_projections(yy, sn); } 103 104OPTS = '|' _ OPT (__ OPT)* 105 106OPT = SKIP | LIMIT | ORDERBY | COUNT | NOIDX | INVERSE 107 108SKIP = "skip" __ (<NUMI> { $$ = _jqp_number(yy, JQP_INT_SKIP, yytext); } | p:PLACEHOLDER { $$ = p; }) { _jqp_set_skip(yy, $$); } 109 110LIMIT = "limit" __ (<NUMI> { $$ = _jqp_number(yy, JQP_INT_LIMIT, yytext); } | p:PLACEHOLDER { $$ = p; }) { _jqp_set_limit(yy, $$); } 111 112COUNT = "count" { _jqp_set_aggregate_count(yy); } 113 114NOIDX = "noidx" { _jqp_set_noidx(yy); } 115 116INVERSE = "inverse" { _jqp_set_inverse(yy); } 117 118ORDERBY = ("asc" | "desc" { _jqp_op_negate(yy); }) 119 __ ( p:ORDERNODES | p:PLACEHOLDER ) 120 { p->string.flavour |= (yy->aux->negate ? JQP_STR_NEGATE : 0); _jqp_op_negate_reset(yy); _jqp_add_orderby(yy, p); } 121 122ORDERNODES = sn:ORDERNODE { _jqp_unit_push(yy, sn); } (n:ORDERNODE { _jqp_unit_push(yy, n); })* { $$ = _jqp_pop_ordernodes(yy, sn) } 123 124ORDERNODE = '/' PROJPROP 125 126PROJNODES = (a:PROJALL { $$ = _jqp_projection(yy, a, 0); } 127 | (sn:PROJNODE { _jqp_unit_push(yy, sn); } (n:PROJNODE { _jqp_unit_push(yy, n);})*) { $$ = _jqp_pop_projection_nodes(yy, sn); }) 128 129PROJALL = "all" { $$ = _jqp_string(yy, JQP_STR_PROJALIAS, "all"); } 130 131PROJNODE = '/' (PROJFIELDS | PROJPROP) 132 133PROJFIELDS = ('{' _ sp:PROJPROP { _jqp_unit_push(yy, sp); } (_ ',' _ p:PROJPROP { _jqp_unit_push(yy, p); } )* _ '}') 134 { $$ = _jqp_pop_projfields_chain(yy, sp); } 135 136PROJPROP = STRN | PSTRP 137 138PROJOIN = ('+' | '-') 139 140PSTRP = <PCHP+> { $$ = _jqp_string(yy, 0, yytext); } 141 142PCHP = '\\' '\\' 143 | '\\' [bfnrt] 144 | '\\' 'u' HEX HEX HEX HEX 145 | !["/{},\t\n\r ] . 146 147 148FILTERFACTOR = (FILTER | '(' FILTEREXPR ')') 149 150FILTEREXPR = ff:FILTERFACTOR { _jqp_unit_push(yy, ff); } 151 (__ j:FILTERJOIN { _jqp_unit_push(yy, j); } __ f:FILTERFACTOR { _jqp_unit_push(yy, f); })* { $$ = _jqp_pop_filter_factor_chain(yy, ff); } 152 153FILTER = ((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); } 154 155FILTERANCHOR = '@' <([a-zA-Z0-9_\-]+)> { $$ = _jqp_string(yy, JQP_STR_ANCHOR, yytext); } 156 157 158NODE = '/' (n:STRN | n:NEXPR | n:STRP) { $$ = _jqp_node(yy, n); } 159 160NEXPR = ('[' _ n:NEXPAIR { _jqp_unit_push(yy, n); } 161 ( __ j:NEXJOIN { _jqp_unit_push(yy, j); } __ np:NEXPAIR { _jqp_unit_push(yy, np); })* _ ']') 162 { $$ = _jqp_pop_expr_chain(yy, n); } 163 164NEXJOIN = (<("and" | "or")> (__ "not" { _jqp_op_negate(yy); })?) { $$ = _jqp_unit_join(yy, yytext); } 165 166NEXPAIR = (l:NEXLEFT _ o:NEXOP _ r:NEXRIGHT) { $$ = _jqp_expr(yy, l, o, r); } 167 168NEXLEFT = (DBLSTAR | STRSTAR | STRN | NEXPRLEFT | STRP) 169 170NEXPRLEFT = ('[' _ l:STRSTAR _ o:NEXOP _ r:NEXRIGHT _ ']') { $$ = _jqp_expr(yy, l, o, r); } 171 172NEXRIGHT = (PLACEHOLDER | VALJ | STRP) 173 174PLACEHOLDER = ':' <([a-zA-Z0-9]+ | '?')> { $$ = _jqp_placeholder(yy, yytext); } 175 176NEXOP = ("not" __ { _jqp_op_negate(yy); })? <("in" | "ni" | "re")> { $$ = _jqp_unit_op(yy, yytext); } 177 | <(">=" | "gte")> { $$ = _jqp_unit_op(yy, yytext); } 178 | <("<=" | "lte")> { $$ = _jqp_unit_op(yy, yytext); } 179 | ('!' _ { _jqp_op_negate(yy); })? <('=' | "eq" | '~')> { $$ = _jqp_unit_op(yy, yytext); } 180 | <('>' | "gt")> { $$ = _jqp_unit_op(yy, yytext); } 181 | <('<' | "lt")> { $$ = _jqp_unit_op(yy, yytext); } 182 | <('~')> { $$ = _jqp_unit_op(yy, yytext); } 183 184STRP = <CHP+> { $$ = _jqp_unescaped_string(yy, 0, yytext); } 185 186DBLSTAR = "**" { $$ = _jqp_unescaped_string(yy, JQP_STR_DBL_STAR, "**"); } 187 188STRSTAR = "*" { $$ = _jqp_unescaped_string(yy, JQP_STR_STAR, "*"); } 189 190STRN = '"' <CHJ+> '"' { $$ = _jqp_unescaped_string(yy, JQP_STR_QUOTED, yytext); } 191 192OBJJ = (s:SOBJJ { _jqp_unit_push(yy, s); } 193 _ (fp:PAIRJ { _jqp_unit_push(yy, fp); } (_ ',' _ p:PAIRJ { _jqp_unit_push(yy, p); })* )? _ '}') 194 { $$ = _jqp_json_collect(yy, JBV_OBJECT, s); } 195 196ARRJ = (s:SARRJ { _jqp_unit_push(yy, s); } 197 _ (fv:VALJ { _jqp_unit_push(yy, fv); } (_ ',' _ v:VALJ { _jqp_unit_push(yy, v); })* )? _ ']') 198 { $$ = _jqp_json_collect(yy, JBV_ARRAY, s); } 199 200SOBJJ = '{' { $$ = _jqp_unit(yy); } 201 202SARRJ = '[' { $$ = _jqp_unit(yy); } 203 204PAIRJ = (s:STRJ _ ':' _ v:VALJ) { $$ = _jqp_json_pair(yy, s, v); } 205 206VALJ = STRJ 207 | NUMJ 208 | OBJJ 209 | ARRJ 210 | "true" { $$ = _jqp_json_true_false_null(yy, "true"); } 211 | "false" { $$ = _jqp_json_true_false_null(yy, "false"); } 212 | "null" { $$ = _jqp_json_true_false_null(yy, "null"); } 213 214STRJ = '"' <(CHJ*)> '"' { $$ = _jqp_json_string(yy, yytext); } 215 216HEX = [0-9A-Fa-f] 217 218CHJ = '\\' '"' 219 | '\\' '\\' 220 | '\\' [bfnrt] 221 | '\\' 'u' HEX HEX HEX HEX 222 | !'"' . 223 224CHP = '\\' '\\' 225 | '\\' [bfnrt] 226 | '\\' 'u' HEX HEX HEX HEX 227 | ![/"[\]=><!\t\n\r() ] . 228 229NUMJ = <('-'? NUMI NUMF? NUME?)> { $$ = _jqp_json_number(yy, yytext); } 230 231NUMPK = <(NUMI)> { $$ = _jqp_json_number(yy, yytext); } 232 233NUMPK_ARR = (s:SARRJ { _jqp_unit_push(yy, s); } 234 _ (fv:NUMPK { _jqp_unit_push(yy, fv); } (_ ',' _ v:NUMPK { _jqp_unit_push(yy, v); })* )? _ ']') 235 { $$ = _jqp_json_collect(yy, JBV_ARRAY, s); } 236 237NUMI = '0' | [1-9] [0-9]* 238 239NUMF = '.' [0-9]+ 240 241NUME = [eE] [+-]? [0-9]+ 242 243_ = SPACE* 244 245__ = SPACE+ 246 247SPACE = ' ' | '\t' | EOL 248 249EOL = ('\r\n' | '\n' | '\r') 250 251EOF = !. 252 253%% 254 255#include "./inc/jqpx.c"