From ab293fccb9a9e660c60a88ce1651cddddebfa862 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Tue, 15 Aug 2017 17:14:19 +0000 Subject: [PATCH] Parse numbers --- runtime.c | 89 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 27 deletions(-) diff --git a/runtime.c b/runtime.c index b2f98cf4..e8456805 100644 --- a/runtime.c +++ b/runtime.c @@ -5923,6 +5923,58 @@ int _read_is_numeric(const char *tok) ((len > 1) && (tok[1] == '.' || isdigit(tok[1])) && (tok[0] == '-' || tok[0] == '+')))); } +int _read_is_hex_digit(char c) +{ + return (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'); +} + +void _read_return_number(void *data, port_type *p, int base, int exact) +{ + // TODO: validation? + p->tok_buf[p->tok_end] = '\0'; // TODO: what if buffer is full? + p->tok_end = 0; // Reset for next atom + make_empty_vector(vec); + make_string(str, p->tok_buf); + vec.num_elements = 2; + vec.elements = (object *) alloca(sizeof(object) * vec.num_elements); + vec.elements[0] = &str; + vec.elements[1] = obj_int2obj(base); +// TODO: need to pass exact or inexact + return_thread_runnable(data, &vec); +} + +void _read_number(void *data, port_type *p, int base, int exact) +{ + char c; + while(1) { + // Read more data into buffer, if needed + if (p->buf_idx == p->mem_buf_len) { + if (!read_from_port(p)){ + _read_return_number(data, p, base, exact); + } + } + c = p->mem_buf[p->buf_idx++]; + p->col_num++; + + if (isdigit(c)) { + if ((base == 2 && c > '1') || + (base == 8 && c > '7')) { + _read_error(data, p, "Illegal digit"); + } + _read_add_to_tok_buf(p, c); + } else if (c == '+' || c == '-' || c == '.') { + _read_add_to_tok_buf(p, c); + } else if (base == 16 && _read_is_hex_digit(c)) { + _read_add_to_tok_buf(p, c); + } else { + p->buf_idx--; + p->col_num--; + _read_return_number(data, p, base, exact); + } + } +} + void _read_return_atom(void *data, object cont, port_type *p) { object sym; @@ -5937,17 +5989,11 @@ void _read_return_atom(void *data, object cont, port_type *p) if (_read_is_numeric(p->tok_buf)) { make_empty_vector(vec); make_string(str, p->tok_buf); - vec.num_elements = 2; vec.elements = (object *) alloca(sizeof(object) * vec.num_elements); vec.elements[0] = &str; vec.elements[1] = obj_int2obj(10); return_thread_runnable(data, &vec); - - //Cyc_string2number_(data, cont, &str); - // TODO: can't do that, need to return_thread_runnable - // for now could cheat (just like with errors): return a specially-marked - // vector and call string->number on buf from there } else if (strncmp("+inf.0", p->tok_buf, 6) == 0 || strncmp("-inf.0", p->tok_buf, 6) == 0) { make_double(d, pow(2.0, 1000000)); @@ -6045,27 +6091,16 @@ void Cyc_io_read_token(void *data, object cont, object port) return_thread_runnable(data, boolean_f); // TODO: character // TODO: numbers - /* - ((eq? #\e next-c) - (parse-number fp toks all? parens ptbl - 10 (lambda (num) - (exact - (string->number (list->string num)))))) - ((eq? #\i next-c) - (parse-number fp toks all? parens ptbl - 10 (lambda (num) - (inexact - (string->number (list->string num)))))) - ((eq? #\b next-c) - (parse-number fp toks all? parens ptbl - 2 (lambda (num) (string->number (list->string num) 2)))) - ((eq? #\o next-c) - (parse-number fp toks all? parens ptbl - 8 (lambda (num) (string->number (list->string num) 8)))) - ((eq? #\x next-c) - (parse-number fp toks all? parens ptbl - 16 (lambda (num) (string->number (list->string num) 16)))) - */ + } else if (c == 'e') { + _read_number(data, p, 10, 1); + } else if (c == 'i') { + _read_number(data, p, 10, 0); + } else if (c == 'b') { + _read_number(data, p, 2, 1); + } else if (c == 'o') { + _read_number(data, p, 8, 1); + } else if (c == 'x') { + _read_number(data, p, 16, 1); } else if (c == '(') { // Vector make_empty_vector(vec); return_thread_runnable(data, &vec);