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[] = {
|
struct cfunction function_list[] = {
|
||||||
{f_true, "true", CALL_BUILTIN_1_1},
|
{f_true, "true", CALL_BUILTIN_1_1},
|
||||||
{f_false, "false", CALL_BUILTIN_1_1},
|
{f_false, "false", CALL_BUILTIN_1_1},
|
||||||
{f_null, "null", CALL_BUILTIN_1_1},
|
{f_null, "null", CALL_BUILTIN_1_1},
|
||||||
{f_plus, "_plus", CALL_BUILTIN_3_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])};
|
struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
"not" { return NOT; }
|
"not" { return NOT; }
|
||||||
"end" { return END; }
|
"end" { return END; }
|
||||||
"//" { return DEFINEDOR; }
|
"//" { return DEFINEDOR; }
|
||||||
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"\$" { return yytext[0];}
|
"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];}
|
||||||
|
|
||||||
\"(\\.|[^\\"])*\" |
|
\"(\\.|[^\\"])*\" |
|
||||||
-?[0-9.]+([eE][+-]?[0-9]+)? {
|
-?[0-9.]+([eE][+-]?[0-9]+)? {
|
||||||
|
28
c/parser.y
28
c/parser.y
@@ -42,11 +42,10 @@
|
|||||||
%nonassoc EQ
|
%nonassoc EQ
|
||||||
%left OR
|
%left OR
|
||||||
%left AND
|
%left AND
|
||||||
%left '+'
|
%left '+' '-'
|
||||||
|
|
||||||
|
|
||||||
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
|
%type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
|
||||||
|
|
||||||
%{
|
%{
|
||||||
#include "lexer.yy.h"
|
#include "lexer.yy.h"
|
||||||
void yyerror(YYLTYPE* loc, block* answer, yyscan_t lexer, const char *s){
|
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)));
|
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 {
|
Exp '+' Exp {
|
||||||
$$ = gen_noop();
|
$$ = gen_binop($1, $3, '+');
|
||||||
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")));
|
Exp '-' Exp {
|
||||||
|
$$ = gen_binop($1, $3, '-');
|
||||||
} |
|
} |
|
||||||
|
|
||||||
Term {
|
Term {
|
||||||
@@ -154,7 +169,6 @@ ElseBody:
|
|||||||
$$ = $2;
|
$$ = $2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ExpD:
|
ExpD:
|
||||||
ExpD '|' ExpD {
|
ExpD '|' ExpD {
|
||||||
$$ = block_join($1, $3);
|
$$ = block_join($1, $3);
|
||||||
|
@@ -167,6 +167,14 @@ null
|
|||||||
"\u0000\u0020\u0000"
|
"\u0000\u0020\u0000"
|
||||||
"\u0000 \u0000\u0000 \u0000"
|
"\u0000 \u0000\u0000 \u0000"
|
||||||
|
|
||||||
|
42 - .
|
||||||
|
11
|
||||||
|
31
|
||||||
|
|
||||||
|
[1,2,3,4,1] - [.,3]
|
||||||
|
1
|
||||||
|
[2,4]
|
||||||
|
|
||||||
#
|
#
|
||||||
# User-defined functions
|
# User-defined functions
|
||||||
# Oh god.
|
# Oh god.
|
||||||
|
Reference in New Issue
Block a user