Improve number-reading in preparation for supporting floating-point.

This commit is contained in:
Jesse D. McDonald 2009-11-14 17:35:34 -06:00
parent 902c489b90
commit 9f0dc52934
1 changed files with 62 additions and 25 deletions

View File

@ -21,6 +21,7 @@ typedef struct reader_state
static value_t read_one_value(reader_state_t *state); static value_t read_one_value(reader_state_t *state);
static value_t read_special(reader_state_t *state); static value_t read_special(reader_state_t *state);
static value_t read_list(reader_state_t *state); static value_t read_list(reader_state_t *state);
static value_t read_fixnum(reader_state_t *state, int radix);
static value_t read_number(reader_state_t *state); static value_t read_number(reader_state_t *state);
static value_t read_string(reader_state_t *state); static value_t read_string(reader_state_t *state);
@ -79,6 +80,7 @@ static value_t read_one_value(reader_state_t *state)
case '(': case '(':
return read_list(state); return read_list(state);
case '-': case '-':
case '+':
case '0' ... '9': case '0' ... '9':
return read_number(state); return read_number(state);
case '\"': case '\"':
@ -215,12 +217,26 @@ static value_t read_list(reader_state_t *state)
return list_root.value; return list_root.value;
} }
static value_t read_number(reader_state_t *state) static short int char_to_digit(int ch)
{
if (isdigit(ch))
{
return ch - '0';
}
else
{
assert(isalpha(ch));
return 10 + (toupper(ch) - 'A');
}
}
static value_t read_fixnum(reader_state_t *state, int radix)
{ {
fixnum_t radix = 10;
fixnum_t num = 0; fixnum_t num = 0;
bool negative = false; bool negative = false;
assert((0 <= radix) && (radix <= 36));
if (state->ch == '-') if (state->ch == '-')
{ {
negative = true; negative = true;
@ -233,6 +249,8 @@ static value_t read_number(reader_state_t *state)
release_assert(isdigit(state->ch)); release_assert(isdigit(state->ch));
if (radix == 0)
{
if (state->ch == '0') if (state->ch == '0')
{ {
next_char(state); next_char(state);
@ -253,15 +271,27 @@ static value_t read_number(reader_state_t *state)
radix = 8; radix = 8;
break; break;
} }
if (radix != 8)
{
/* Make sure we have at least one digit; if octal then the '0' counts instead */
release_assert(isalnum(state->ch));
release_assert(char_to_digit(state->ch) < radix);
}
}
else
{
radix = 10;
}
} }
while (isxdigit(state->ch)) while (isalnum(state->ch))
{ {
fixnum_t digit = isdigit(state->ch) fixnum_t digit = char_to_digit(state->ch);
? (state->ch - '0')
: (10 + (toupper(state->ch) - 'A')); if (digit >= radix)
break;
release_assert(digit < radix);
release_assert(num <= (FIXNUM_MAX/radix)); release_assert(num <= (FIXNUM_MAX/radix));
num *= radix; num *= radix;
@ -277,6 +307,13 @@ static value_t read_number(reader_state_t *state)
return fixnum_value(num); return fixnum_value(num);
} }
static value_t read_number(reader_state_t *state)
{
value_t v = read_fixnum(state, 0);
release_assert(!issymbol(state->ch));
return v;
}
static value_t read_string(reader_state_t *state) static value_t read_string(reader_state_t *state)
{ {
char *buffer = (char*)malloc(128); char *buffer = (char*)malloc(128);
@ -484,7 +521,7 @@ static value_t read_weak_box(reader_state_t *state)
static value_t read_definition(reader_state_t *state) static value_t read_definition(reader_state_t *state)
{ {
fixnum_t ref = get_fixnum(read_number(state)); fixnum_t ref = get_fixnum(read_fixnum(state, 0));
gc_root_t place_root; gc_root_t place_root;
value_t v; value_t v;
@ -514,7 +551,7 @@ static value_t read_placeholder(reader_state_t *state)
} }
else else
{ {
return get_placeholder(state, get_fixnum(read_number(state))); return get_placeholder(state, get_fixnum(read_fixnum(state, 0)));
} }
} }