]> granicus.if.org Git - jq/commitdiff
Add update operators (+=, -=, *=, /= and //=)
authorStephen Dolan <mu@netsoc.tcd.ie>
Tue, 11 Sep 2012 22:55:59 +0000 (23:55 +0100)
committerStephen Dolan <mu@netsoc.tcd.ie>
Tue, 11 Sep 2012 22:55:59 +0000 (23:55 +0100)
c/lexer.l
c/parser.y
c/testdata

index 9c20a95302bca291aa17c0fdac1ed6818c60d29d..dd93f4974a0e424ed6e42abf182ec627fc1e1d22 100644 (file)
--- a/c/lexer.l
+++ b/c/lexer.l
@@ -22,7 +22,6 @@
 "==" { return EQ; }
 "as" { return AS; }
 "def" { return DEF; }
-"|=" { return SETPIPE; }
 "if" { return IF; }
 "then" { return THEN; }
 "else" { return ELSE; }
 "not" { return NOT; }
 "end" { return END; }
 "//" { return DEFINEDOR; }
+"|=" { return SETPIPE; }
+"+=" { return SETPLUS; }
+"-=" { return SETMINUS; }
+"*=" { return SETMULT; }
+"/=" { return SETDIV; }
+"//=" { return SETDEFINEDOR; }
 "."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];}
 
 \"(\\.|[^\\\"])*\" |
index 70fb711677ffd312bc17e203e92556486d54f762..d8780a877614bec2244ff5f4da6f8a43214bed47 100644 (file)
@@ -46,7 +46,6 @@
 %token DEFINEDOR "//"
 %token AS "as"
 %token DEF "def"
-%token SETPIPE "|="
 %token IF "if"
 %token THEN "then"
 %token ELSE "else"
 %token AND "and"
 %token OR "or"
 %token NOT "not"
-
+%token SETPIPE "|="
+%token SETPLUS "+="
+%token SETMINUS "-="
+%token SETMULT "*="
+%token SETDIV "/="
+%token SETDEFINEDOR "//="
 
  /* revolting hack */
 %left ';'
 %left '|'
 %left ','
 %right "//"
-%nonassoc '=' SETPIPE
+%nonassoc '=' SETPIPE SETPLUS SETMINUS SETMULT SETDIV SETDEFINEDOR
 %nonassoc EQ
 %left OR
 %left AND
@@ -138,6 +142,16 @@ static block gen_binop(block a, block b, int op) {
   return c;
 }
 
+static block gen_update(block a, block op, int optype) {
+  block assign = a;
+  block_append(&assign, gen_op_simple(DUP));
+  if (optype) {
+    op = gen_binop(gen_noop(), op, optype);
+  }
+  block_append(&assign, op);
+  return gen_assign(assign);
+}
+
 %}
 
 %%
@@ -198,11 +212,12 @@ Exp "//" Exp {
   $$ = gen_definedor($1, $3);
 } |
 
+Exp "//=" Exp {
+  $$ = gen_update($1, gen_definedor(gen_noop(), $3), 0);
+} |
+
 Exp "|=" Exp {
-  block assign = $1;
-  block_append(&assign, gen_op_simple(DUP));
-  block_append(&assign, $3);
-  $$ = gen_assign(assign);
+  $$ = gen_update($1, $3, 0);
 } |
 
 Exp '|' Exp { 
@@ -217,18 +232,34 @@ Exp '+' Exp {
   $$ = gen_binop($1, $3, '+');
 } |
 
+Exp "+=" Exp {
+  $$ = gen_update($1, $3, '+');
+} |
+
 Exp '-' Exp {
   $$ = gen_binop($1, $3, '-');
 } |
 
+Exp "-=" Exp {
+  $$ = gen_update($1, $3, '-');
+} |
+
 Exp '*' Exp {
   $$ = gen_binop($1, $3, '*');
 } |
 
+Exp "*=" Exp {
+  $$ = gen_update($1, $3, '*');
+} |
+
 Exp '/' Exp {
   $$ = gen_binop($1, $3, '/');
 } |
 
+Exp "/=" Exp {
+  $$ = gen_update($1, $3, '/');
+} |
+
 Exp "==" Exp {
   $$ = gen_binop($1, $3, EQ);
 } |
index bd1d7f25bbc1ab543e7dcf3d3c2997f95df594e2..e17f2bb72ea43dd465aa8be2e3d9c237e0848698 100644 (file)
@@ -270,6 +270,13 @@ def id(x):x; 2000 as $x | def f(x):1 as $x | id([$x, x, x]); def g(x): 100 as $x
 {"foo": 42}
 {"foo": 43}
 
+.[] += 2, .[] *= 2, .[] -= 2, .[] /= 2
+[1,3,5]
+[3,5,7]
+[2,6,10]
+[-1,1,3]
+[0.5, 1.5, 2.5]
+
 .[0].a |= {"old":., "new":(.+1)}
 [{"a":1,"b":2}]
 [{"a":{"old":1, "new":2},"b":2}]
@@ -305,6 +312,10 @@ def inc(x): x |= .+1; inc(.[].a)
 [{"foo":[1,2], "bar": 42}, {"foo":[1], "bar": null}, {"foo":[null,false,3], "bar": 18}, {"foo":[], "bar":42}, {"foo": [null,false,null], "bar": 41}]
 [[1,2], [1], [3], [42], [41]]
 
+.[] //= 42
+["hello",true,false,[false],null]
+["hello",true,42,[false],42]
+
 .[] | [.[0] and .[1], .[0] or .[1]]
 [[true,[]], [false,1], [42,null], [null,false]]
 [true,true]