commit 5b18649ed4a2610a4c367b800133e6a84f11bd60
Author: William Casarin <jb55@jb55.com>
Date: Sat, 16 Dec 2017 19:00:32 -0800
bcalc: init at something not working
Diffstat:
A | lexer.l | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | num.h | | | 37 | +++++++++++++++++++++++++++++++++++++ |
A | parser.y | | | 68 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | unit.c | | | 54 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
4 files changed, 211 insertions(+), 0 deletions(-)
diff --git a/lexer.l b/lexer.l
@@ -0,0 +1,52 @@
+
+
+%option noyywrap
+
+%{
+#include <stdio.h>
+#include <gmp.h>
+
+#define YY_DECL int yylex()
+ extern YYSTYPE yylval;
+
+#include "parser.tab.h"
+
+%}
+
+%%
+
+[ \t] ; // ignore all whitespace
+
+[mM]?[bB][tT][cC] {
+ int ism = yytext[0] == 'm' || yytext[0] == 'M';
+ yylval.unit = ism? UNIT_MBTC : UNIT_BTC;
+ return T_UNIT;
+}
+
+[mM]?[sS][aA][tT][sS]? {
+ int ism = yytext[0] == 'm' || yytext[0] == 'M';
+ yylval.unit = ism ? UNIT_MSATOSHI : UNIT_SATOSHI;
+ return T_UNIT;
+}
+
+[0-9]*\.[0-9]+ {
+ double d = atof(yytext);
+ yylval.dubs = d;
+ return T_FLOAT;
+}
+
+[0-9]+ {
+ mpq_init(yylval.rval);
+ mpz_set_str(yylval.rval, yytext, 10);
+ return T_INT;
+}
+
+\n {return T_NEWLINE;}
+"+" {return T_PLUS;}
+"-" {return T_MINUS;}
+"*" {return T_MULTIPLY;}
+"/" {return T_DIVIDE;}
+"(" {return T_LEFT;}
+")" {return T_RIGHT;}
+
+%%
diff --git a/num.h b/num.h
@@ -0,0 +1,37 @@
+
+#ifndef UNIT_H
+#define UNIT_H
+
+#include <stdint.h>
+
+#define MSATOSHI 100000000000LL
+#define SATOSHI 100000000LL
+#define FINNEY 10000000LL
+#define BITS 1000000LL
+#define MBTC 1000LL
+
+enum unit {
+ UNIT_BTC,
+ UNIT_MBTC,
+ UNIT_BITS,
+ UNIT_FINNEY,
+ UNIT_SATOSHI,
+ UNIT_MSATOSHI,
+};
+
+enum num_type {
+ TYPE_INT,
+ TYPE_FLOAT
+};
+
+struct num
+{
+ enum num_type type;
+ enum unit unit;
+ union {
+ int64_t intval;
+ double floatval;
+ };
+};
+
+#endif /* UNIT_H */
diff --git a/parser.y b/parser.y
@@ -0,0 +1,68 @@
+
+%{
+
+#include <stdio.h>
+#include <num.h>
+#include <stdlib.h>
+
+extern int yylex();
+extern int yyparse();
+extern FILE* yyin;
+
+char buffer[255];
+
+void yyerror(const char* s);
+%}
+
+%union {
+ int64_t intval;
+ double floatval;
+ enum units unit;
+}
+
+%token<intval> T_INT
+%token<floatval> T_FLOAT
+%token<unit> T_UNIT
+%token T_PLUS T_MINUS T_MULTIPLY T_DIVIDE T_LEFT T_RIGHT
+%token T_NEWLINE T_QUIT
+%left T_PLUS T_MINUS
+%left T_MULTIPLY T_DIVIDE
+
+%type<rval> expr
+
+%start calc
+
+%%
+
+calc:
+ | calc line
+;
+
+line: T_NEWLINE
+ | expr T_NEWLINE { mpq_out_str(stdout, 10, $1); printf("\n"); }
+;
+
+expr: T_INT { ; }
+ | expr T_PLUS expr { mpq_add($$, $1, $3); }
+ | expr T_MINUS expr { mpq_sub($$, $1, $3); }
+ | expr T_MULTIPLY expr { mpq_mul($$, $1, $3); }
+ | expr T_DIVIDE expr { mpq_div($$, $1, $3); }
+ | T_LEFT expr T_RIGHT { mpq_init($$); mpq_set($$, $2); }
+;
+
+%%
+
+int main() {
+ yyin = stdin;
+
+ do {
+ yyparse();
+ } while(!feof(yyin));
+
+ return 0;
+}
+
+void yyerror(const char* s) {
+ fprintf(stderr, "Parse error: %s\n", s);
+ exit(1);
+}
diff --git a/unit.c b/unit.c
@@ -0,0 +1,54 @@
+
+#include <assert.h>
+#include "num.h"
+
+void
+num_init(struct num *num) {
+ num->type = TYPE_INT;
+ num->unit = UNIT_BTC;
+ num->intval = 0LL;
+}
+
+static int64_t
+num_to_msat(struct num *num) {
+ if (num->type == TYPE_FLOAT) {
+ double val = num->floatval;
+ switch (num->unit) {
+ case UNIT_MSATOSHI:
+ assert("fractional millisatoshis are not yet supported");
+ return (int64_t)val;
+ case UNIT_SATOSHI:
+ return (int64_t)(val * 1000);
+ case UNIT_FINNEY:
+ return (int64_t)(val * 10000);
+ case UNIT_BITS:
+ return (int64_t)(val * 100000);
+ case UNIT_MBTC:
+ return (int64_t)(val * 100000000);
+ case UNIT_BTC:
+ return (int64_t)(val * 100000000000);
+ }
+ }
+
+ int64_t val = num->intval;
+ switch (num->unit) {
+ case UNIT_MSATOSHI:
+ return val;
+ case UNIT_SATOSHI:
+ return val * 1000;
+ case UNIT_FINNEY:
+ return val * 10000;
+ case UNIT_BITS:
+ return val * 100000;
+ case UNIT_MBTC:
+ return val * 100000000;
+ case UNIT_BTC:
+ return val * 100000000000;
+ }
+}
+
+
+int64_t
+num_add(struct num *a, struct num *b) {
+ return (num_to_msat(a) + num_to_msat(b));
+}