%token INVALID_CHARACTER
%token IDENT
%token FIELD
%token BINDING
%token LITERAL
%token FORMAT
String:
StringStart QQString QQSTRING_END {
$$ = $2;
jv_free($1);
};
Expr:
Expr "//" Expr {
$$ = gen_definedor($1, $3);
} |
Expr '=' Expr {
$$ = gen_call("_assign", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Term %prec NONOPT {
$$ = $1;
}
TopLevel:
Module Imports Query {
*answer = BLOCK($1, $2, gen_op_simple(TOP), $3);
} |
Module Imports FuncDefs {
*answer = BLOCK($1, $2, $3);
}
Query:
FuncDef Query %prec FUNCDEF {
$$ = block_bind_referenced($1, $2, OP_IS_CALL_PSEUDO);
} |
Expr {
$$ = $1;
}
Query '|' Query {
$$ = block_join($1, $3);
} |
Query ',' Query {
$$ = gen_both($1, $3);
}
Term FIELD '?' {
$$ = gen_index_opt($1, gen_const($2));
} |
Term '?' {
$$ = gen_try($1, gen_op_simple(BACKTRACK));
}
Expr "or" Expr {
$$ = gen_or($1, $3);
} |
Expr "and" Expr {
$$ = gen_and($1, $3);
} |
Expr "==" Expr {
$$ = gen_binop($1, $3, EQ);
}
LITERAL {
$$ = gen_const($1);
} |
IDENT {
const char *s = jv_string_value($1);
if (strcmp(s, "false") == 0)
$$ = gen_const(jv_false());
else if (strcmp(s, "true") == 0)
$$ = gen_const(jv_true());
else if (strcmp(s, "null") == 0)
$$ = gen_const(jv_null());
Term FIELD %prec NONOPT {
$$ = gen_index($1, gen_const($2));
} |
Term '[' Query ']' %prec NONOPT {
$$ = gen_index($1, $3);
}
Term '[' ']' %prec NONOPT {
$$ = block_join($1, gen_op_simple(EACH));
} |
Term '[' Query ':' Query ']' %prec NONOPT {
$$ = gen_slice_index($1, $3, $5, INDEX);
}
Expr '+' Expr {
$$ = gen_binop($1, $3, '+');
} |
Expr "+=" Expr {
$$ = gen_update($1, $3, '+');
}
Expr "//" Expr {
$$ = gen_definedor($1, $3);
} |
Expr "//=" Expr {
$$ = gen_definedor_assign($1, $3);
}
"if" Query "then" Query ElseBody {
$$ = gen_cond($2, $4, $5);
} |
"try" Expr "catch" Expr {
$$ = gen_try($2, $4);
}
"label" BINDING '|' Query {
jv v = jv_string_fmt("*label-%s", jv_string_value($2));
$$ = gen_location(@$, locations, gen_label(jv_string_value(v), $4));
} |
BREAK BINDING {
jv v = jv_string_fmt("*label-%s", jv_string_value($2));
"reduce" Expr "as" Patterns '(' Query ';' Query ')' {
$$ = gen_reduce($2, $4, $6, $8);
} |
"foreach" Expr "as" Patterns '(' Query ';' Query ';' Query ')' {
$$ = gen_foreach($2, $4, $6, $8, $10);
}
REC {
$$ = gen_call("recurse", gen_noop());
}
Expr "as" Patterns '|' Query {
$$ = gen_destructure($1, $3, $5);
} |
BINDING {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1)));
jv_free($1);
}
Params:
Param {
$$ = $1;
} |
Params ';' Param {
$$ = BLOCK($1, $3);
}
FuncDef:
"def" IDENT ':' Query ';' {
$$ = gen_function(jv_string_value($2), gen_noop(), $4);
jv_free($2);
}
RepPatterns:
RepPatterns "?//" Pattern {
$$ = BLOCK($1, gen_destructure_alt($3));
} |
Pattern {
$$ = gen_destructure_alt($1);
}
static block gen_update(block object, block val, int optype) {
block tmp = gen_op_var_fresh(STOREV, "tmp");
return BLOCK(gen_op_simple(DUP),
val,
tmp,
gen_call("_modify", BLOCK(gen_lambda(object),
gen_lambda(gen_binop(gen_noop(),
gen_op_bound(LOADV, tmp),
optype)))));
}
Expr "|=" Expr {
$$ = gen_call("_modify", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Expr "+=" Expr {
$$ = gen_update($1, $3, '+');
}
Expr '=' Expr {
$$ = gen_call("_assign", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Expr SETMOD Expr {
$$ = gen_update($1, $3, '%');
}
static block gen_format(block a, jv fmt) {
return BLOCK(a, gen_call("format", gen_lambda(gen_const(fmt))));
}
void yyerror(YYLTYPE* loc, block* answer, int* errors,
struct locfile* locations, struct lexer_param* lexer_param_ptr, const char *s){
(*errors)++;
locfile_locate(locations, *loc, "jq: error: %s", s);
}