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.
This commit is contained in:
Jesse D. McDonald 2009-11-13 23:12:55 -06:00
parent 861f1f7617
commit 0404777049
2 changed files with 109 additions and 56 deletions

View File

@ -8,11 +8,11 @@
#(1 #f) #(1 #f)
#() #()
1 1
"\x02\x80\x01\x00"; (set! 128 (cons 1 0)) "\x02\x80\x01\x00"; (set! f0 (cons g1 nil))
254 0xfe
128 0x80
2 0x02
255 0xff
) )
#S(#="template" #S(#="template"
#( #(
@ -21,57 +21,57 @@
#(#f) #(#f)
"\x40\xff\xfe" ; i0 ctx k "\x40\xff\xfe" ; i0 ctx k
1 1
"\x00\x80\x03\xfd\; (set! 128 (car 253)) "\x00\x80\x03\xfd\; (set! f0 (car argv))
\x0a\x80\x40\x80\; (set! 128 (fix* 64 128)) \x0a\x80\x40\x80\; (set! f0 (fix* i0 f0))
\x02\x80\x80\x00"; (set! 128 (cons 128 0)) \x02\x80\x80\x00"; (set! f0 (cons f0 nil))
66 0x42 ; i2
128 0x80 ; f0
1 0x01 ; g1
65 0x41 ; i1
) )
1 1
) )
"\x80" ; f0 "\x80" ; f0
2 2
"\x09\x80\x40\x03\; (set! 128 (fix- 64 3)) "\x09\x80\x40\x03\; (set! f0 (fix- i0 g3))
\x02\x80\x80\x00\; (set! 128 (cons 128 0)) \x02\x80\x80\x00\; (set! f0 (cons f0 nil))
\x00\x81\x1b\x02"; (set! 129 (lambda 2)) \x00\x81\x1b\x02"; (set! f1 (lambda g2))
1 0x01
128 0x80
129 0x81
255 0xff
) )
1 1
) )
#() #()
2 2
"\x00\x80\x03\xfd\; (set! 128 (car 253)) "\x00\x80\x03\xfd\; (set! f0 (car argv))
\x0d\x81\x80\x03\; (set! 129 (fix< 128 3)) \x0d\x81\x80\x03\; (set! f1 (fix< f0 g3))
\x81\x81\x01\x02\; (set! 129 (if 129 1 2)) \x81\x81\x01\x02\; (set! f1 (if f1 g1 g2))
\x00\x81\x1b\x81"; (set! 129 (lambda 129)) \x00\x81\x1b\x81"; (set! f1 (lambda f1))
129 0x81
0 0x00
254 0xfe
255 0xff
) )
#f #f
) )
"\xfe\xff" ; k ctx "\xfe\xff" ; k ctx
0 0
"" ""
1 0x01
253 0xfd
64 0x40
65 0x41
) )
#="string->number" #="string->number"
) )
#() #()
1 1
"\x00\x80\x1b\x01"; (set! 128 (lambda 1)) "\x00\x80\x1b\x01"; (set! f0 (lambda g1))
2 0x02
253 0xfd
128 0x80
255 0xff
) )
; vim:set sw=2 expandtab syntax=: ; vim:set syntax= sw=2 expandtab:

View File

@ -215,6 +215,7 @@ static value_t read_list(reader_state_t *state)
static value_t read_number(reader_state_t *state) static value_t read_number(reader_state_t *state)
{ {
fixnum_t radix = 10;
fixnum_t num = 0; fixnum_t num = 0;
bool negative = false; bool negative = false;
@ -230,11 +231,40 @@ static value_t read_number(reader_state_t *state)
release_assert(isdigit(state->ch)); release_assert(isdigit(state->ch));
while (isdigit(state->ch)) if (state->ch == '0')
{ {
release_assert(num <= (FIXNUM_MAX/10)); next_char(state);
num *= 10;
num += (state->ch - '0'); 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); next_char(state);
} }
@ -346,11 +376,26 @@ static value_t read_string(reader_state_t *state)
if (skip_ws) if (skip_ws)
{ {
/* Slightly different from the normal skip_whitespace(); bool hit_eol = false;
* Assumes first char is space, and bounded by '\n' afterward. */
/* Slightly different from the normal skip_whitespace(); skips
* whitespace through the _second_ EOL following the backslash. */
do { do {
if (state->ch == '\n')
{
if (!hit_eol)
{
hit_eol = true;
}
else
{
next_char(state);
break;
}
}
next_char(state); next_char(state);
} while (isspace(state->ch) && (state->ch != '\n')); } while (isspace(state->ch));
} }
else else
{ {
@ -585,21 +630,29 @@ static void next_char(reader_state_t *state)
static void skip_whitespace(reader_state_t *state) static void skip_whitespace(reader_state_t *state)
{ {
while (isspace(state->ch)) for (;;)
next_char(state);
/* Comments count as whitespace */
if (state->ch == ';')
{ {
do { if (isspace(state->ch))
{
next_char(state); next_char(state);
}
if (state->ch == '\n') else if (state->ch == ';')
{ {
/* Comments count as whitespace */
do {
next_char(state); next_char(state);
break;
} if (state->ch == '\n')
} while (state->ch != EOF); {
next_char(state);
break;
}
} while (state->ch != EOF);
}
else
{
break;
}
} }
} }