bcalc

cli bitcoin unit calculator
git clone git://jb55.com/bcalc
Log | Files | Refs | README | LICENSE

commit 9fe02d49770a983fc3ecacc376e6b56528793c50
parent e2f92ff60ce794f7d50f3b838dd703aa4d0e157f
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 19 Dec 2017 11:22:13 -0800

ops: support scalar multiplication/division

Diffstat:
Mlexer.l | 1-
Mnum.c | 32++++++++++++++++++++++++++++++--
Mnum.h | 1+
Mparser.y | 38++++++++++++++++++++++----------------
4 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/lexer.l b/lexer.l @@ -2,7 +2,6 @@ %{ #include <stdio.h> -#include <gmp.h> #include "num.h" #define YY_DECL int yylex() diff --git a/num.c b/num.c @@ -31,6 +31,8 @@ num_to_msat(struct num *num) { return (int64_t)(val * MBTC); case UNIT_BTC: return (int64_t)(val * BTC); + case UNIT_NONE: + assert(!"got UNIT_NONE in num_to_msat"); } } @@ -48,6 +50,8 @@ num_to_msat(struct num *num) { return val * MBTC; case UNIT_BTC: return val * BTC; + case UNIT_NONE: + assert(!"got UNIT_NONE in num_to_msat"); } } @@ -77,21 +81,44 @@ unit_msat_multiple(enum unit format) { case UNIT_BITS: return BITS; case UNIT_MBTC: return MBTC; case UNIT_BTC: return BTC; + case UNIT_NONE: assert(!"got UNIT_NONE in num_to_msat"); } } void num_mul(struct num *dst, struct num *a, struct num *b) { + assert(b->unit == UNIT_NONE); dst->type = TYPE_INT; dst->unit = UNIT_MSATOSHI; - dst->intval = num_to_msat(a) * num_to_msat(b); + dst->intval = num_to_msat(a) * (b->type == TYPE_FLOAT? b->floatval + : b->intval); } void num_div(struct num *dst, struct num *a, struct num *b) { + assert(b->unit == UNIT_NONE); dst->type = TYPE_INT; dst->unit = UNIT_MSATOSHI; - dst->intval = num_to_msat(a) / num_to_msat(b); + dst->intval = num_to_msat(a) / (b->type == TYPE_FLOAT? b->floatval + : b->intval); +} + +void +num_init_float(struct num *num, double d, enum unit unit) { + num_init(num); + num->floatval = d; + num->type = TYPE_FLOAT; + num->unit = unit; + if (unit != UNIT_NONE) num_assign(num, num); +} + +void +num_init_int(struct num *num, int64_t val, enum unit unit) { + num_init(num); + num->intval = val; + num->type = TYPE_INT; + num->unit = unit; + if (unit != UNIT_NONE) num_assign(num, num); } void @@ -157,5 +184,6 @@ unit_name(enum unit unit) { case UNIT_BITS: return "bits"; case UNIT_MBTC: return "mBTC"; case UNIT_BTC: return "BTC"; + case UNIT_NONE: assert(!"got UNIT_NONE in num_to_msat"); } } diff --git a/num.h b/num.h @@ -19,6 +19,7 @@ enum unit { UNIT_FINNEY, UNIT_SATOSHI, UNIT_MSATOSHI, + UNIT_NONE, }; enum num_type { diff --git a/parser.y b/parser.y @@ -26,7 +26,7 @@ int g_print_unit; %left T_PLUS T_MINUS %left T_MULTIPLY T_DIVIDE -%type<num> expr +%type<num> expr unit_number number mul_expr div_expr %start calc @@ -40,24 +40,30 @@ line: T_NEWLINE | expr T_NEWLINE { num_print(&$1, g_output_format, g_print_unit); } ; -expr: T_INT T_UNIT { num_init(&$$); - $$.intval = $1; - $$.type = TYPE_INT; - $$.unit = $2; - num_assign(&$$, &$$); - } - | T_FLOAT T_UNIT { num_init(&$$); - $$.floatval = $1; - $$.type = TYPE_FLOAT; - $$.unit = $2; - num_assign(&$$, &$$); - } +unit_number: + T_INT T_UNIT { num_init_int(&$$, $1, $2); } + | T_FLOAT T_UNIT { num_init_float(&$$, $1, $2); } + ; + + +number: T_INT { num_init_int(&$$, $1, UNIT_NONE); } + | T_FLOAT { num_init_float(&$$, $1, UNIT_NONE); } + ; + +mul_expr: number T_MULTIPLY unit_number { num_mul(&$$, &$3, &$1); } + | unit_number T_MULTIPLY number { num_mul(&$$, &$1, &$3); } + ; + +div_expr: number T_DIVIDE unit_number { num_div(&$$, &$3, &$1); } + | unit_number T_DIVIDE number { num_div(&$$, &$1, &$3); } + ; + +expr: unit_number | expr T_PLUS expr { num_add(&$$, &$1, &$3); } | expr T_MINUS expr { num_sub(&$$, &$1, &$3); } - /* | expr T_MULTIPLY expr { num_mul(&$$, &$1, &$3); } */ - /* | expr T_DIVIDE expr { num_div(&$$, &$1, &$3); } */ + | mul_expr + | div_expr | T_LEFT expr T_RIGHT { num_init(&$$); num_assign(&$$, &$2); } ; %% -