Improve number-reading in preparation for supporting floating-point.
This commit is contained in:
parent
902c489b90
commit
9f0dc52934
87
reader.c
87
reader.c
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue