From: Stephen Roantree Date: Sun, 7 Oct 2012 21:34:12 +0000 (+0100) Subject: Add <,>,<=,>= binops X-Git-Tag: jq-1.1~7^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0618e61e0bd0a58cd222bb4905c51178fe332525;p=jq Add <,>,<=,>= binops --- diff --git a/builtin.c b/builtin.c index 1eee5bb..c6ff785 100644 --- a/builtin.c +++ b/builtin.c @@ -4,6 +4,12 @@ #include "parser.h" #include "locfile.h" +enum { + CMP_OP_LESS, + CMP_OP_GREATER, + CMP_OP_LESSEQ, + CMP_OP_GREATEREQ +} _cmp_op; static void f_plus(jv input[], jv output[]) { jv_free(input[0]); @@ -114,6 +120,42 @@ static void f_equal(jv input[], jv output[]) { output[0] = jv_bool(jv_equal(input[2], input[1])); } +static void order_cmp(jv input[], jv output[], int op) { + 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) { + double da = jv_number_value(a); + double db = jv_number_value(b); + output[0] = jv_bool((op == CMP_OP_LESS && da < db) || + (op == CMP_OP_LESSEQ && da <= db) || + (op == CMP_OP_GREATEREQ && da >= db) || + (op == CMP_OP_GREATER && da > db)); + } else { + output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to compare order of %s wrt %s", + jv_kind_name(jv_get_kind(a)), + jv_kind_name(jv_get_kind(b)))); + jv_free(a); + jv_free(b); + } +} + +static void f_less(jv input[], jv output[]) { + order_cmp(input, output, CMP_OP_LESS); +} + +static void f_greater(jv input[], jv output[]) { + order_cmp(input, output, CMP_OP_GREATER); +} + +static void f_lesseq(jv input[], jv output[]) { + order_cmp(input, output, CMP_OP_LESSEQ); +} + +static void f_greatereq(jv input[], jv output[]) { + order_cmp(input, output, CMP_OP_GREATEREQ); +} + static void f_tonumber(jv input[], jv output[]) { if (jv_get_kind(input[0]) == JV_KIND_NUMBER) { output[0] = input[0]; @@ -202,6 +244,10 @@ static struct cfunction function_list[] = { {f_tonumber, "tonumber", CALL_BUILTIN_1_1}, {f_tostring, "tostring", CALL_BUILTIN_1_1}, {f_equal, "_equal", CALL_BUILTIN_3_1}, + {f_less, "_less", CALL_BUILTIN_3_1}, + {f_greater, "_greater", CALL_BUILTIN_3_1}, + {f_lesseq, "_lesseq", CALL_BUILTIN_3_1}, + {f_greatereq, "_greatereq", CALL_BUILTIN_3_1}, {f_length, "length", CALL_BUILTIN_1_1}, {f_type, "type", CALL_BUILTIN_1_1}, {f_add, "add", CALL_BUILTIN_1_1}, diff --git a/lexer.l b/lexer.l index fe0049a..a353d89 100644 --- a/lexer.l +++ b/lexer.l @@ -48,7 +48,9 @@ "*=" { return SETMULT; } "/=" { return SETDIV; } "//=" { return SETDEFINEDOR; } -"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];} +"<=" { return LESSEQ; } +">=" { return GREATEREQ; } +"."|"="|";"|","|":"|"|"|"+"|"-"|"*"|"/"|"\$"|"<"|">" { return yytext[0];} "["|"{"|"(" { return enter(yytext[0], YY_START, yyscanner); diff --git a/parser.y b/parser.y index 0fda65b..94700ae 100644 --- a/parser.y +++ b/parser.y @@ -59,6 +59,8 @@ %token SETMULT "*=" %token SETDIV "/=" %token SETDEFINEDOR "//=" +%token LESSEQ "<=" +%token GREATEREQ ">=" %token QQSTRING_START %token QQSTRING_TEXT @@ -77,6 +79,7 @@ %nonassoc EQ %left '+' '-' %left '*' '/' +%right '<' '>' LESSEQ GREATEREQ %type Exp Term MkDict MkDictPair ExpD ElseBody QQString FuncDef FuncDefs @@ -137,6 +140,10 @@ static block gen_binop(block a, block b, int op) { case '*': funcname = "_multiply"; break; case '/': funcname = "_divide"; break; case EQ: funcname = "_equal"; break; + case '<': funcname = "_less"; break; + case '>': funcname = "_greater"; break; + case LESSEQ: funcname = "_lesseq"; break; + case GREATEREQ: funcname = "_greatereq"; break; } assert(funcname); @@ -273,6 +280,22 @@ Exp "==" Exp { $$ = gen_binop($1, $3, EQ); } | +Exp '<' Exp { + $$ = gen_binop($1, $3, '<'); +} | + +Exp '>' Exp { + $$ = gen_binop($1, $3, '>'); +} | + +Exp "<=" Exp { + $$ = gen_binop($1, $3, LESSEQ); +} | + +Exp ">=" Exp { + $$ = gen_binop($1, $3, GREATEREQ); +} | + QQSTRING_START QQString QQSTRING_END { $$ = $2; } | diff --git a/testdata b/testdata index 307eaa6..c37dee9 100644 --- a/testdata +++ b/testdata @@ -348,3 +348,12 @@ def inc(x): x |= .+1; inc(.[].a) [.[] | not] [1,0,false,null,true,"hello"] [false,false,true,true,false,false] + +# Check numeric comparison binops +[10 > 0, 10 > 10, 10 > 20, 10 < 0, 10 < 10, 10 < 20] +{} +[true,false,false,false,false,true] + +[10 >= 0, 10 >= 10, 10 >= 20, 10 <= 0, 10 <= 10, 10 <= 20] +{} +[true,true,false,false,true,true] \ No newline at end of file