mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Subtraction - as expected for numbers, ruby-style set diff for arrays.
This commit is contained in:
34
c/builtin.c
34
c/builtin.c
@@ -37,10 +37,44 @@ static void f_plus(jv input[], jv output[]) {
|
||||
}
|
||||
}
|
||||
|
||||
static void f_minus(jv input[], jv output[]) {
|
||||
jv_free(input[0]);
|
||||
jv a = input[2];
|
||||
jv b = input[1];
|
||||
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
|
||||
output[0] = jv_number(jv_number_value(a) - jv_number_value(b));
|
||||
} else if (jv_get_kind(a) == JV_KIND_ARRAY && jv_get_kind(b) == JV_KIND_ARRAY) {
|
||||
jv out = jv_array();
|
||||
for (int i=0; i<jv_array_length(jv_copy(a)); i++) {
|
||||
jv x = jv_array_get(jv_copy(a), i);
|
||||
int include = 1;
|
||||
for (int j=0; j<jv_array_length(jv_copy(b)); j++) {
|
||||
if (jv_equal(jv_copy(x), jv_array_get(jv_copy(b), j))) {
|
||||
include = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (include)
|
||||
out = jv_array_append(out, jv_copy(x));
|
||||
jv_free(x);
|
||||
}
|
||||
jv_free(a);
|
||||
jv_free(b);
|
||||
output[0] = out;
|
||||
} else {
|
||||
output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to subtract %s and %s",
|
||||
jv_kind_name(jv_get_kind(a)),
|
||||
jv_kind_name(jv_get_kind(b))));
|
||||
jv_free(a);
|
||||
jv_free(b);
|
||||
}
|
||||
}
|
||||
|
||||
struct cfunction function_list[] = {
|
||||
{f_true, "true", CALL_BUILTIN_1_1},
|
||||
{f_false, "false", CALL_BUILTIN_1_1},
|
||||
{f_null, "null", CALL_BUILTIN_1_1},
|
||||
{f_plus, "_plus", CALL_BUILTIN_3_1},
|
||||
{f_minus, "_minus", CALL_BUILTIN_3_1},
|
||||
};
|
||||
struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
|
||||
|
@@ -22,7 +22,7 @@
|
||||
"not" { return NOT; }
|
||||
"end" { return END; }
|
||||
"//" { return DEFINEDOR; }
|
||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];}
|
||||
|
||||
\"(\\.|[^\\"])*\" |
|
||||
-?[0-9.]+([eE][+-]?[0-9]+)? {
|
||||
|
28
c/parser.y
28
c/parser.y
@@ -42,11 +42,10 @@
|
||||
%nonassoc EQ
|
||||
%left OR
|
||||
%left AND
|
||||
%left '+'
|
||||
%left '+' '-'
|
||||
|
||||
|
||||
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
|
||||
|
||||
%{
|
||||
#include "lexer.yy.h"
|
||||
void yyerror(YYLTYPE* loc, block* answer, yyscan_t lexer, const char *s){
|
||||
@@ -64,6 +63,21 @@ static block gen_index(block obj, block key) {
|
||||
return block_join(obj, block_join(gen_subexp(key), gen_op_simple(INDEX)));
|
||||
}
|
||||
|
||||
static block gen_binop(block a, block b, char op) {
|
||||
const char* funcname = 0;
|
||||
switch (op) {
|
||||
case '+': funcname = "_plus"; break;
|
||||
case '-': funcname = "_minus"; break;
|
||||
}
|
||||
assert(funcname);
|
||||
|
||||
block c = gen_noop();
|
||||
block_append(&c, gen_subexp(a));
|
||||
block_append(&c, gen_subexp(b));
|
||||
block_append(&c, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, funcname)));
|
||||
return c;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%%
|
||||
@@ -136,10 +150,11 @@ Exp ',' Exp {
|
||||
} |
|
||||
|
||||
Exp '+' Exp {
|
||||
$$ = gen_noop();
|
||||
block_append(&$$, gen_subexp($1));
|
||||
block_append(&$$, gen_subexp($3));
|
||||
block_append(&$$, gen_op_call(CALL_1_1, gen_op_block_unbound(CLOSURE_REF, "_plus")));
|
||||
$$ = gen_binop($1, $3, '+');
|
||||
} |
|
||||
|
||||
Exp '-' Exp {
|
||||
$$ = gen_binop($1, $3, '-');
|
||||
} |
|
||||
|
||||
Term {
|
||||
@@ -154,7 +169,6 @@ ElseBody:
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
|
||||
ExpD:
|
||||
ExpD '|' ExpD {
|
||||
$$ = block_join($1, $3);
|
||||
|
@@ -167,6 +167,14 @@ null
|
||||
"\u0000\u0020\u0000"
|
||||
"\u0000 \u0000\u0000 \u0000"
|
||||
|
||||
42 - .
|
||||
11
|
||||
31
|
||||
|
||||
[1,2,3,4,1] - [.,3]
|
||||
1
|
||||
[2,4]
|
||||
|
||||
#
|
||||
# User-defined functions
|
||||
# Oh god.
|
||||
|
Reference in New Issue
Block a user