refactor number reader

This commit is contained in:
Yuichi Nishiwaki 2015-05-27 23:40:01 +09:00
parent 15449354c6
commit 4cd8dcab60
1 changed files with 61 additions and 28 deletions

View File

@ -224,67 +224,102 @@ read_symbol(pic_state *pic, struct pic_port *port, int c)
return pic_obj_value(sym); return pic_obj_value(sym);
} }
static size_t static unsigned
read_uinteger(pic_state *pic, struct pic_port *port, int c, char buf[]) read_uinteger(pic_state *pic, struct pic_port *port, int c)
{ {
size_t i = 0; unsigned u = 0;
if (! isdigit(c)) { if (! isdigit(c)) {
read_error(pic, "expected one or more digits"); read_error(pic, "expected one or more digits");
} }
buf[i++] = (char)c; u = c - '0';
while (isdigit(c = peek(port))) { while (isdigit(c = peek(port))) {
buf[i++] = (char)next(port); u = u * 10 + next(port) - '0';
} }
buf[i] = '\0'; return u;
return i;
} }
static size_t static int
read_suffix(pic_state *pic, struct pic_port *port, char buf[]) read_suffix(pic_state *pic, struct pic_port *port)
{ {
size_t i = 0; int c, s = 1;
int c;
c = peek(port); c = peek(port);
if (c != 'e' && c != 'E') { if (c != 'e' && c != 'E') {
return i; return 0;
} }
buf[i++] = (char)next(port); next(port);
switch ((c = next(port))) { switch ((c = next(port))) {
case '-': case '-':
s = -1;
case '+': case '+':
buf[i++] = (char)c;
c = next(port); c = next(port);
default: default:
return i + read_uinteger(pic, port, c, buf + i); return s * read_uinteger(pic, port, c);
} }
} }
static pic_value static pic_value
read_unsigned(pic_state *pic, struct pic_port *port, int c) read_unsigned(pic_state *pic, struct pic_port *port, int c)
{ {
char buf[256]; unsigned u, w = 0;
size_t i; int exp, s, i, e;
double f;
i = read_uinteger(pic, port, c, buf); u = read_uinteger(pic, port, c);
switch (peek(port)) { switch (peek(port)) {
case '.': case '.':
buf[i++] = (char)next(port); next(port);
i += read_uinteger(pic, port, next(port), buf + i); w = 0, f = 1;
read_suffix(pic, port, buf + i); while (isdigit(c = peek(port))) {
return pic_float_value(atof(buf)); w = w * 10 + next(port) - '0';
f /= 10;
}
f = u + w * f;
exp = read_suffix(pic, port);
if (exp >= 0) {
s = 0;
} else {
exp = -exp;
s = 1;
}
e = 10;
for (i = 0; exp; ++i) {
if ((exp & 1) != 0) {
f = s ? f / e : (f * e);
}
e *= e;
exp >>= 1;
}
return pic_float_value(f);
default: default:
read_suffix(pic, port, buf + i); exp = read_suffix(pic, port);
return pic_int_value((int)(atof(buf))); if (exp >= 0) {
s = 0;
} else {
exp = -exp;
s = 1;
}
e = 10;
for (i = 0; exp; ++i) {
if ((exp & 1) != 0) {
u = s ? u / e : (u * e);
}
e *= e;
exp >>= 1;
}
return pic_int_value(u);
} }
} }
@ -495,7 +530,6 @@ read_blob(pic_state *pic, struct pic_port *port, int c)
{ {
int nbits, n; int nbits, n;
size_t len, i; size_t len, i;
char buf[256];
unsigned char *dat; unsigned char *dat;
pic_blob *blob; pic_blob *blob;
@ -517,8 +551,7 @@ read_blob(pic_state *pic, struct pic_port *port, int c)
dat = NULL; dat = NULL;
c = next(port); c = next(port);
while ((c = skip(port, c)) != ')') { while ((c = skip(port, c)) != ')') {
read_uinteger(pic, port, c, buf); n = read_uinteger(pic, port, c);
n = atoi(buf);
if (n < 0 || (1 << nbits) <= n) { if (n < 0 || (1 << nbits) <= n) {
read_error(pic, "invalid element in bytevector literal"); read_error(pic, "invalid element in bytevector literal");
} }