diff --git a/builtin.c b/builtin.c index 32b67ccc..76e559ea 100644 --- a/builtin.c +++ b/builtin.c @@ -65,6 +65,15 @@ static jv f_plus(jv input, jv a, jv b) { } } +static jv f_negate(jv input) { + if (jv_get_kind(input) != JV_KIND_NUMBER) { + return type_error(input, "cannot be negated"); + } + jv ret = jv_number(-jv_number_value(input)); + jv_free(input); + return ret; +} + static jv f_minus(jv input, jv a, jv b) { jv_free(input); if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) { @@ -462,6 +471,7 @@ static jv f_error(jv input, jv msg) { static struct cfunction function_list[] = { {(cfunction_ptr)f_plus, "_plus", 3}, + {(cfunction_ptr)f_negate, "_negate", 1}, {(cfunction_ptr)f_minus, "_minus", 3}, {(cfunction_ptr)f_multiply, "_multiply", 3}, {(cfunction_ptr)f_divide, "_divide", 3}, diff --git a/lexer.l b/lexer.l index fd0e120e..9d826efa 100644 --- a/lexer.l +++ b/lexer.l @@ -73,7 +73,7 @@ struct lexer_param; yylval->literal = jv_string_sized(yytext + 1, yyleng - 1); return FORMAT; } --?[0-9.]+([eE][+-]?[0-9]+)? { +[0-9.]+([eE][+-]?[0-9]+)? { yylval->literal = jv_parse_sized(yytext, yyleng); return LITERAL; } diff --git a/parser.y b/parser.y index a1be0b7f..92cd9db8 100644 --- a/parser.y +++ b/parser.y @@ -260,6 +260,10 @@ Exp "+=" Exp { $$ = gen_update($1, $3, '+'); } | +'-' Exp { + $$ = BLOCK($2, gen_call("_negate", gen_noop())); +} | + Exp '-' Exp { $$ = gen_binop($1, $3, '-'); } | diff --git a/testdata b/testdata index 4a998d8e..83f91dae 100644 --- a/testdata +++ b/testdata @@ -21,6 +21,11 @@ null null 1 + +-1 +null +-1 + # FIXME: much more number testing needed {} @@ -197,6 +202,14 @@ null "wtasdf" 2.0 +2-1 +null +1 + +2-(-1) +null +3 + 1e+0+0.001e3 "I wonder what this will be?" 20e-1