From df195b31873010f18883446c6e0e629a594badc5 Mon Sep 17 00:00:00 2001 From: Stephen Dolan Date: Tue, 11 Sep 2012 23:55:59 +0100 Subject: [PATCH] Add update operators (+=, -=, *=, /= and //=) --- c/lexer.l | 7 ++++++- c/parser.y | 45 ++++++++++++++++++++++++++++++++++++++------- c/testdata | 11 +++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/c/lexer.l b/c/lexer.l index 9c20a95..dd93f49 100644 --- 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; } @@ -32,6 +31,12 @@ "not" { return NOT; } "end" { return END; } "//" { return DEFINEDOR; } +"|=" { return SETPIPE; } +"+=" { return SETPLUS; } +"-=" { return SETMINUS; } +"*=" { return SETMULT; } +"/=" { return SETDIV; } +"//=" { return SETDEFINEDOR; } "."|"="|";"|"["|"]"|","|":"|"("|")"|"{"|"}"|"|"|"+"|"-"|"*"|"/"|"\$" { return yytext[0];} \"(\\.|[^\\\"])*\" | diff --git a/c/parser.y b/c/parser.y index 70fb711..d8780a8 100644 --- a/c/parser.y +++ b/c/parser.y @@ -46,7 +46,6 @@ %token DEFINEDOR "//" %token AS "as" %token DEF "def" -%token SETPIPE "|=" %token IF "if" %token THEN "then" %token ELSE "else" @@ -55,14 +54,19 @@ %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); } | diff --git a/c/testdata b/c/testdata index bd1d7f2..e17f2bb 100644 --- a/c/testdata +++ b/c/testdata @@ -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] -- 2.40.0