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
"\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:

View File

@ -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);
} while (isspace(state->ch) && (state->ch != '\n'));
break;
}
}
next_char(state);
} while (isspace(state->ch));
}
else
{
@ -585,12 +630,15 @@ 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 (;;)
{
if (isspace(state->ch))
{
next_char(state);
}
else if (state->ch == ';')
{
/* Comments count as whitespace */
do {
next_char(state);
@ -601,6 +649,11 @@ static void skip_whitespace(reader_state_t *state)
}
} while (state->ch != EOF);
}
else
{
break;
}
}
}
/* vim:set sw=2 expandtab: */