apply negative prefix in parser

Previously a negative prefix was applied in the lexer, but that's kind
of hacky and messy so I handed it to the parser.
This commit is contained in:
r4 2021-11-22 20:56:06 +01:00
parent dfc515b7df
commit 0fcef2a860

22
main.c
View File

@ -62,15 +62,12 @@ void tokenize(char *expr) {
size_t paren_depth = 0; size_t paren_depth = 0;
bool can_be_neg_num = true;
char *curr = expr; char *curr = expr;
for (char c = *curr; c != 0; c = *(++curr)) { for (char c = *curr; c != 0; c = *(++curr)) {
if (c == ' ') if (c == ' ')
continue; continue;
if (IS_FLOAT(c) || if (IS_FLOAT(c)) {
(can_be_neg_num && c == '-' && IS_FLOAT(curr[1]))) {
char buf[16]; char buf[16];
buf[0] = c; buf[0] = c;
size_t i = 1; size_t i = 1;
@ -84,8 +81,6 @@ void tokenize(char *expr) {
real num = strtod(buf, NULL); real num = strtod(buf, NULL);
push_tok((Tok){.kind = TokNum, .Num = num}); push_tok((Tok){.kind = TokNum, .Num = num});
can_be_neg_num = false;
continue; continue;
} }
@ -101,8 +96,6 @@ void tokenize(char *expr) {
buf[i++] = 0; buf[i++] = 0;
push_tok((Tok){.kind = TokFunc, .Str = buf}); push_tok((Tok){.kind = TokFunc, .Str = buf});
can_be_neg_num = false;
continue; continue;
} }
@ -132,8 +125,6 @@ void tokenize(char *expr) {
fprintf(stderr, "Error: unrecognized token at %zd: '%c'\n", curr - expr, c); fprintf(stderr, "Error: unrecognized token at %zd: '%c'\n", curr - expr, c);
exit(1); exit(1);
} }
can_be_neg_num = c != ')';
} }
if (paren_depth > 0) { if (paren_depth > 0) {
@ -168,6 +159,7 @@ void print_toks() {
printf("\n"); printf("\n");
} }
/* Delete tokens from begin to end (excluding end itself). */
void del_toks(Tok *begin, Tok *end) { void del_toks(Tok *begin, Tok *end) {
memmove(begin, end, (toks_size - (end - toks)) * sizeof(Tok)); memmove(begin, end, (toks_size - (end - toks)) * sizeof(Tok));
toks_size -= end - begin; toks_size -= end - begin;
@ -180,6 +172,16 @@ real eval(Tok *t) {
} }
while (1) { while (1) {
/* Collapse factor. */
if (t[1].kind == TokOp && t[1].Char == '-') {
if (t[2].kind != TokNum) {
fprintf(stderr, "Error: expected number token after minus factor\n");
exit(1);
}
t[2].Num *= -1.0;
del_toks(t + 1, t + 2);
}
/* Collapse parentheses. */ /* Collapse parentheses. */
if (t[1].kind == TokOp && t[1].Char == '(') { if (t[1].kind == TokOp && t[1].Char == '(') {
real res = eval(t + 1); real res = eval(t + 1);