From 04047770492c9d27a765f66f21925a6c1e1c209a Mon Sep 17 00:00:00 2001 From: Jesse McDonald Date: Fri, 13 Nov 2009 23:12:55 -0600 Subject: [PATCH] Fix interaction between comments and whitespace in the reader. Add support for fixnums in binary (0b), octal (0), and hexadecimal (0x). Minor changes to the example input program to improve readability. --- core-image.rla | 74 ++++++++++++++++++++-------------------- reader.c | 91 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 109 insertions(+), 56 deletions(-) diff --git a/core-image.rla b/core-image.rla index f9cf792..da70159 100644 --- a/core-image.rla +++ b/core-image.rla @@ -8,11 +8,11 @@ #(1 #f) #() 1 - "\x02\x80\x01\x00"; (set! 128 (cons 1 0)) - 254 - 128 - 2 - 255 + "\x02\x80\x01\x00"; (set! f0 (cons g1 nil)) + 0xfe + 0x80 + 0x02 + 0xff ) #S(#="template" #( @@ -21,57 +21,57 @@ #(#f) "\x40\xff\xfe" ; i0 ctx k 1 - "\x00\x80\x03\xfd\; (set! 128 (car 253)) - \x0a\x80\x40\x80\; (set! 128 (fix* 64 128)) - \x02\x80\x80\x00"; (set! 128 (cons 128 0)) - 66 - 128 - 1 - 65 + "\x00\x80\x03\xfd\; (set! f0 (car argv)) + \x0a\x80\x40\x80\; (set! f0 (fix* i0 f0)) + \x02\x80\x80\x00"; (set! f0 (cons f0 nil)) + 0x42 ; i2 + 0x80 ; f0 + 0x01 ; g1 + 0x41 ; i1 ) 1 ) "\x80" ; f0 2 - "\x09\x80\x40\x03\; (set! 128 (fix- 64 3)) - \x02\x80\x80\x00\; (set! 128 (cons 128 0)) - \x00\x81\x1b\x02"; (set! 129 (lambda 2)) - 1 - 128 - 129 - 255 + "\x09\x80\x40\x03\; (set! f0 (fix- i0 g3)) + \x02\x80\x80\x00\; (set! f0 (cons f0 nil)) + \x00\x81\x1b\x02"; (set! f1 (lambda g2)) + 0x01 + 0x80 + 0x81 + 0xff ) 1 ) #() 2 - "\x00\x80\x03\xfd\; (set! 128 (car 253)) - \x0d\x81\x80\x03\; (set! 129 (fix< 128 3)) - \x81\x81\x01\x02\; (set! 129 (if 129 1 2)) - \x00\x81\x1b\x81"; (set! 129 (lambda 129)) - 129 - 0 - 254 - 255 + "\x00\x80\x03\xfd\; (set! f0 (car argv)) + \x0d\x81\x80\x03\; (set! f1 (fix< f0 g3)) + \x81\x81\x01\x02\; (set! f1 (if f1 g1 g2)) + \x00\x81\x1b\x81"; (set! f1 (lambda f1)) + 0x81 + 0x00 + 0xfe + 0xff ) #f ) "\xfe\xff" ; k ctx 0 "" - 1 - 253 - 64 - 65 + 0x01 + 0xfd + 0x40 + 0x41 ) #="string->number" ) #() 1 - "\x00\x80\x1b\x01"; (set! 128 (lambda 1)) - 2 - 253 - 128 - 255 + "\x00\x80\x1b\x01"; (set! f0 (lambda g1)) + 0x02 + 0xfd + 0x80 + 0xff ) -; vim:set sw=2 expandtab syntax=: +; vim:set syntax= sw=2 expandtab: diff --git a/reader.c b/reader.c index 9abaf77..fe9d476 100644 --- a/reader.c +++ b/reader.c @@ -215,6 +215,7 @@ static value_t read_list(reader_state_t *state) static value_t read_number(reader_state_t *state) { + fixnum_t radix = 10; fixnum_t num = 0; bool negative = false; @@ -230,11 +231,40 @@ static value_t read_number(reader_state_t *state) release_assert(isdigit(state->ch)); - while (isdigit(state->ch)) + if (state->ch == '0') { - release_assert(num <= (FIXNUM_MAX/10)); - num *= 10; - num += (state->ch - '0'); + next_char(state); + + switch (state->ch) + { + case 'X': + case 'x': + next_char(state); + radix = 16; + break; + case 'B': + case 'b': + next_char(state); + radix = 2; + break; + default: + radix = 8; + break; + } + } + + while (isxdigit(state->ch)) + { + fixnum_t digit = isdigit(state->ch) + ? (state->ch - '0') + : (10 + (toupper(state->ch) - 'A')); + + release_assert(digit < radix); + release_assert(num <= (FIXNUM_MAX/radix)); + + num *= radix; + num += digit; + next_char(state); } @@ -346,11 +376,26 @@ static value_t read_string(reader_state_t *state) if (skip_ws) { - /* Slightly different from the normal skip_whitespace(); - * Assumes first char is space, and bounded by '\n' afterward. */ + bool hit_eol = false; + + /* Slightly different from the normal skip_whitespace(); skips + * whitespace through the _second_ EOL following the backslash. */ do { + if (state->ch == '\n') + { + if (!hit_eol) + { + hit_eol = true; + } + else + { + next_char(state); + break; + } + } + next_char(state); - } while (isspace(state->ch) && (state->ch != '\n')); + } while (isspace(state->ch)); } else { @@ -585,21 +630,29 @@ static void next_char(reader_state_t *state) static void skip_whitespace(reader_state_t *state) { - while (isspace(state->ch)) - next_char(state); - - /* Comments count as whitespace */ - if (state->ch == ';') + for (;;) { - do { + if (isspace(state->ch)) + { next_char(state); - - if (state->ch == '\n') - { + } + else if (state->ch == ';') + { + /* Comments count as whitespace */ + do { next_char(state); - break; - } - } while (state->ch != EOF); + + if (state->ch == '\n') + { + next_char(state); + break; + } + } while (state->ch != EOF); + } + else + { + break; + } } }