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_special(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_string(reader_state_t *state);
@ -79,6 +80,7 @@ static value_t read_one_value(reader_state_t *state)
case '(':
return read_list(state);
case '-':
case '+':
case '0' ... '9':
return read_number(state);
case '\"':
@ -215,12 +217,26 @@ static value_t read_list(reader_state_t *state)
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;
bool negative = false;
assert((0 <= radix) && (radix <= 36));
if (state->ch == '-')
{
negative = true;
@ -233,35 +249,49 @@ static value_t read_number(reader_state_t *state)
release_assert(isdigit(state->ch));
if (state->ch == '0')
if (radix == 0)
{
next_char(state);
switch (state->ch)
if (state->ch == '0')
{
case 'X':
case 'x':
next_char(state);
radix = 16;
break;
case 'B':
case 'b':
next_char(state);
radix = 2;
break;
default:
radix = 8;
break;
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;
}
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)
? (state->ch - '0')
: (10 + (toupper(state->ch) - 'A'));
fixnum_t digit = char_to_digit(state->ch);
if (digit >= radix)
break;
release_assert(digit < radix);
release_assert(num <= (FIXNUM_MAX/radix));
num *= radix;
@ -277,6 +307,13 @@ static value_t read_number(reader_state_t *state)
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)
{
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)
{
fixnum_t ref = get_fixnum(read_number(state));
fixnum_t ref = get_fixnum(read_fixnum(state, 0));
gc_root_t place_root;
value_t v;
@ -514,7 +551,7 @@ static value_t read_placeholder(reader_state_t *state)
}
else
{
return get_placeholder(state, get_fixnum(read_number(state)));
return get_placeholder(state, get_fixnum(read_fixnum(state, 0)));
}
}