Expand expr's support for numeric literals

- Support hex prefix 0x or OX
- Support scientific notation

Also, reconcile the bitwise complement operator with C (use ~ instead of ^).
This commit is contained in:
smurf3tte 2020-12-17 17:01:43 -08:00 committed by TryTwo
parent 7842f9a715
commit 11851a01e6
1 changed files with 37 additions and 29 deletions

View File

@ -160,10 +160,10 @@ static int expr_prec(enum expr_type a, enum expr_type b) {
return (left && prec[a] >= prec[b]) || (prec[a] > prec[b]); return (left && prec[a] >= prec[b]) || (prec[a] > prec[b]);
} }
#define isfirstvarchr(c) \ #define isfirstvarchr(c) \
(((unsigned char)c >= '@' && c != '^' && c != '|') || c == '$') (((unsigned char)c >= '@' && c != '^' && c != '|' && c != '~') || c == '$')
#define isvarchr(c) \ #define isvarchr(c) \
(((unsigned char)c >= '@' && c != '^' && c != '|') || c == '$' || \ (((unsigned char)c >= '@' && c != '^' && c != '|' && c != '~') || c == '$' || \
c == '#' || (c >= '0' && c <= '9')) c == '#' || (c >= '0' && c <= '9'))
static struct { static struct {
@ -172,7 +172,7 @@ static struct {
} OPS[] = { } OPS[] = {
{"-u", OP_UNARY_MINUS}, {"-u", OP_UNARY_MINUS},
{"!u", OP_UNARY_LOGICAL_NOT}, {"!u", OP_UNARY_LOGICAL_NOT},
{"^u", OP_UNARY_BITWISE_NOT}, {"~u", OP_UNARY_BITWISE_NOT},
{"**", OP_POWER}, {"**", OP_POWER},
{"*", OP_MULTIPLY}, {"*", OP_MULTIPLY},
{"/", OP_DIVIDE}, {"/", OP_DIVIDE},
@ -199,7 +199,7 @@ static struct {
them at the end */ them at the end */
{"-", OP_UNARY_MINUS}, {"-", OP_UNARY_MINUS},
{"!", OP_UNARY_LOGICAL_NOT}, {"!", OP_UNARY_LOGICAL_NOT},
{"^", OP_UNARY_BITWISE_NOT}, {"~", OP_UNARY_BITWISE_NOT},
}; };
static enum expr_type expr_op(const char *s, size_t len, int unary) { static enum expr_type expr_op(const char *s, size_t len, int unary) {
@ -212,30 +212,24 @@ static enum expr_type expr_op(const char *s, size_t len, int unary) {
return OP_UNKNOWN; return OP_UNKNOWN;
} }
static double expr_parse_number(const char *s, size_t len) { static double expr_parse_number(const char* s, size_t len) {
double num = 0; double num = 0;
unsigned int frac = 0; char buf[32];
unsigned int digits = 0; char* sz = buf;
for (unsigned int i = 0; i < len; i++) { char* end = NULL;
if (s[i] == '.' && frac == 0) { if (len >= sizeof(buf)) {
frac++; sz = (char*)calloc(1, len + 1);
continue; if (sz == NULL) {
}
if (isdigit(s[i])) {
digits++;
if (frac > 0) {
frac++;
}
num = num * 10 + (s[i] - '0');
} else {
return NAN; return NAN;
} }
} }
while (frac > 1) { strncpy(sz, s, len);
num = num / 10; sz[len] = '\0';
frac--; num = strtod(sz, &end);
if (sz != buf) {
free(sz);
} }
return (digits > 0 ? num : NAN); return (end == sz + len ? num : NAN);
} }
/* /*
@ -446,9 +440,23 @@ static int expr_next_token(const char *s, size_t len, int *flags) {
return -1; // unexpected number return -1; // unexpected number
} }
*flags = EXPR_TOP | EXPR_TCLOSE; *flags = EXPR_TOP | EXPR_TCLOSE;
while ((c == '.' || isdigit(c)) && i < len) { if (c == '0') {
i++; i++;
c = s[i]; if (i < len && (s[i] == 'x' || s[i] == 'X')) {
i++;
for (; i < len && isxdigit(s[i]); i++)
;
return i;
}
}
for (; i < len && (s[i] == '.' || isdigit(s[i])); i++)
;
if (i < len && (s[i] == 'e' || s[i] == 'E')) {
i++;
if (i < len && (s[i] == '+' || s[i] == '-'))
i++;
for (; i < len && isdigit(s[i]); i++)
;
} }
return i; return i;
} else if (isfirstvarchr(c)) { } else if (isfirstvarchr(c)) {
@ -626,8 +634,8 @@ static struct expr *expr_create(const char *s, size_t len,
case '-': case '-':
tok = "-u"; tok = "-u";
break; break;
case '^': case '~':
tok = "^u"; tok = "~u";
break; break;
case '!': case '!':
tok = "!u"; tok = "!u";