<requirement name="lexical-scanning" stories="PARSE-001">
%token INVALID_CHARACTER
%token <literal> IDENT
%token <literal> FIELD
%token <literal> BINDING
%token <literal> LITERAL
%token <literal> FORMAT
</requirement>
<requirement name="literals-strings-interpolation" stories="PARSE-002">
String:
StringStart QQString QQSTRING_END {
$$ = $2;
jv_free($1);
};
</requirement>
<requirement name="core-filter-grammar" stories="PARSE-003">
Expr:
Expr "//" Expr {
$$ = gen_definedor($1, $3);
} |
Expr '=' Expr {
$$ = gen_call("_assign", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Term %prec NONOPT {
$$ = $1;
}
</requirement>
<requirement name="declarations-control-rejection" stories="PARSE-004">
TopLevel:
Module Imports Query {
*answer = BLOCK($1, $2, gen_op_simple(TOP), $3);
} |
Module Imports FuncDefs {
*answer = BLOCK($1, $2, $3);
}
</requirement>
<requirement name="stream-valued-filters" stories="CORE-001">
Query:
FuncDef Query %prec FUNCDEF {
$$ = block_bind_referenced($1, $2, OP_IS_CALL_PSEUDO);
} |
Expr {
$$ = $1;
}
</requirement>
<requirement name="filter-composition" stories="CORE-002">
Query '|' Query {
$$ = block_join($1, $3);
} |
Query ',' Query {
$$ = gen_both($1, $3);
}
</requirement>
<requirement name="errors-and-optional-evaluation" stories="CORE-003">
Term FIELD '?' {
$$ = gen_index_opt($1, gen_const($2));
} |
Term '?' {
$$ = gen_try($1, gen_op_simple(BACKTRACK));
}
</requirement>
<requirement name="truthiness-comparison" stories="CORE-004">
Expr "or" Expr {
$$ = gen_or($1, $3);
} |
Expr "and" Expr {
$$ = gen_and($1, $3);
} |
Expr "==" Expr {
$$ = gen_binop($1, $3, EQ);
}
</requirement>
<requirement name="value-constants" stories="VALUE-001">
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());
</requirement>
<requirement name="field-index-access" stories="VALUE-002">
Term FIELD %prec NONOPT {
$$ = gen_index($1, gen_const($2));
} |
Term '[' Query ']' %prec NONOPT {
$$ = gen_index($1, $3);
}
</requirement>
<requirement name="slices-and-iteration" stories="VALUE-003">
Term '[' ']' %prec NONOPT {
$$ = block_join($1, gen_op_simple(EACH));
} |
Term '[' Query ':' Query ']' %prec NONOPT {
$$ = gen_slice_index($1, $3, $5, INDEX);
}
</requirement>
<requirement name="arithmetic-structural-operators" stories="FLOW-001">
Expr '+' Expr {
$$ = gen_binop($1, $3, '+');
} |
Expr "+=" Expr {
$$ = gen_update($1, $3, '+');
}
</requirement>
<requirement name="boolean-alternative-operators" stories="FLOW-002">
Expr "//" Expr {
$$ = gen_definedor($1, $3);
} |
Expr "//=" Expr {
$$ = gen_definedor_assign($1, $3);
}
</requirement>
<requirement name="conditionals-exception-flow" stories="FLOW-003">
"if" Query "then" Query ElseBody {
$$ = gen_cond($2, $4, $5);
} |
"try" Expr "catch" Expr {
$$ = gen_try($2, $4);
}
</requirement>
<requirement name="labels-and-breaks" stories="FLOW-004">
"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));
</requirement>
<requirement name="reductions-and-iteration-control" stories="FLOW-005">
"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);
}
</requirement>
<requirement name="recursive-generators" stories="FLOW-006">
REC {
$$ = gen_call("recurse", gen_noop());
}
</requirement>
<requirement name="variable-bindings" stories="FUNC-001">
Expr "as" Patterns '|' Query {
$$ = gen_destructure($1, $3, $5);
} |
BINDING {
$$ = gen_location(@$, locations, gen_op_unbound(LOADV, jv_string_value($1)));
jv_free($1);
}
</requirement>
<requirement name="function-parameters" stories="FUNC-002">
Params:
Param {
$$ = $1;
} |
Params ';' Param {
$$ = BLOCK($1, $3);
}
</requirement>
<requirement name="function-definitions" stories="FUNC-003">
FuncDef:
"def" IDENT ':' Query ';' {
$$ = gen_function(jv_string_value($2), gen_noop(), $4);
jv_free($2);
}
</requirement>
<requirement name="destructuring-alternatives" stories="FUNC-004">
RepPatterns:
RepPatterns "?//" Pattern {
$$ = BLOCK($1, gen_destructure_alt($3));
} |
Pattern {
$$ = gen_destructure_alt($1);
}
</requirement>
<requirement name="path-access-mutation" stories="PATH-002">
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)))));
}
</requirement>
<requirement name="assignment-operators" stories="PATH-003">
Expr "|=" Expr {
$$ = gen_call("_modify", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Expr "+=" Expr {
$$ = gen_update($1, $3, '+');
}
</requirement>
<requirement name="complex-assignments" stories="PATH-004">
Expr '=' Expr {
$$ = gen_call("_assign", BLOCK(gen_lambda($1), gen_lambda($3)));
} |
Expr SETMOD Expr {
$$ = gen_update($1, $3, '%');
}
</requirement>
<requirement name="formats-and-serialization" stories="TEXT-002">
static block gen_format(block a, jv fmt) {
return BLOCK(a, gen_call("format", gen_lambda(gen_const(fmt))));
}
</requirement>
<requirement name="parser-diagnostics" stories="IO-002">
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);
}
</requirement>
<unattached story="architecture-foundation"/>
<unattached story="EXEC-001"/>
<unattached story="EXEC-002"/>
<unattached story="EXEC-003"/>
<unattached story="VALUE-004"/>
<unattached story="CONF-001"/>
<unattached story="PATH-001"/>
<unattached story="DATA-001"/>
<unattached story="DATA-002"/>
<unattached story="DATA-003"/>
<unattached story="DATA-004"/>
<unattached story="TEXT-001"/>
<unattached story="TEXT-003"/>
<unattached story="TEXT-004"/>
<unattached story="IO-001"/>
<unattached story="IO-003"/>
<unattached story="CONF-002"/>
<unattached story="CONF-003"/>Run artifact