1
0
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:
Stephen Dolan
2012-09-10 16:49:25 +01:00
parent 65ce73deb4
commit 6f3abbac62
4 changed files with 64 additions and 8 deletions

View File

@@ -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])};

View File

@@ -22,7 +22,7 @@
"not" { return NOT; }
"end" { return END; }
"//" { return DEFINEDOR; }
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];}
\"(\\.|[^\\"])*\" |
-?[0-9.]+([eE][+-]?[0-9]+)? {

View File

@@ -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);

View File

@@ -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.