]> granicus.if.org Git - jq/commitdiff
Multiplication and division operators.
authorStephen Dolan <mu@netsoc.tcd.ie>
Mon, 10 Sep 2012 15:57:17 +0000 (16:57 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Mon, 10 Sep 2012 15:57:17 +0000 (16:57 +0100)
It is an error to use these on anything but numbers. Maybe later
implementing python/ruby-style ("a" * 100) might be handy.

c/builtin.c
c/lexer.l
c/parser.y
c/testdata

index 65ecb52ca00d8065bc8f27d0b976e2dad0890802..b65bb09b3c589cb7bdcfc40eceecb0f37f37f94b 100644 (file)
@@ -70,11 +70,43 @@ static void f_minus(jv input[], jv output[]) {
   }
 }
 
+static void f_multiply(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 {
+    output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to multiply %s and %s",
+                                                  jv_kind_name(jv_get_kind(a)),
+                                                  jv_kind_name(jv_get_kind(b))));
+    jv_free(a);
+    jv_free(b);
+  }  
+}
+
+static void f_divide(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 {
+    output[0] = jv_invalid_with_msg(jv_string_fmt("Attempted to divide %s by %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},
+  {f_multiply, "_multiply", CALL_BUILTIN_3_1},
+  {f_divide, "_divide", CALL_BUILTIN_3_1},
 };
 struct symbol_table builtins = {function_list, sizeof(function_list)/sizeof(function_list[0])};
index 1b74d43ffada18560227462349d1343fa33e5aad..1794b9f1f9499a983f842046047941c7830b195d 100644 (file)
--- a/c/lexer.l
+++ b/c/lexer.l
@@ -22,7 +22,7 @@
 "not" { return NOT; }
 "end" { return END; }
 "//" { return DEFINEDOR; }
-"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"\$" { return yytext[0];}
+"."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];}
 
 \"(\\.|[^\\"])*\" |
 -?[0-9.]+([eE][+-]?[0-9]+)? { 
index 72b91a1aff7dc6a290e98e6a45b4b9ceb7a74328..225a324e7abb5e4bcc5a9f29684ee63d2a278aed 100644 (file)
@@ -43,6 +43,7 @@
 %left OR
 %left AND
 %left '+' '-'
+%left '*' '/'
 
 
 %type <blk> Exp Term MkDict MkDictPair ExpD ElseBody
@@ -68,6 +69,8 @@ static block gen_binop(block a, block b, char op) {
   switch (op) {
   case '+': funcname = "_plus"; break;
   case '-': funcname = "_minus"; break;
+  case '*': funcname = "_multiply"; break;
+  case '/': funcname = "_divide"; break;
   }
   assert(funcname);
 
@@ -157,6 +160,14 @@ Exp '-' Exp {
   $$ = gen_binop($1, $3, '-');
 } |
 
+Exp '*' Exp {
+  $$ = gen_binop($1, $3, '*');
+} |
+
+Exp '/' Exp {
+  $$ = gen_binop($1, $3, '/');
+} |
+
 Term { 
   $$ = $1; 
 }
index 6386ac08d455cc04a21b88fb364b5b5bb67638c0..eb9f0c5faef72a467da30cc276fd94950a814c10 100644 (file)
@@ -175,6 +175,14 @@ null
 1
 [2,4]
 
+[10 * 20, 20 / .]
+4
+[200, 5]
+
+1 + 2 * 2 + 10 / 2
+null
+10
+
 #
 # User-defined functions
 # Oh god.