Closed stef closed 2 years ago
Sorry for the late reply.
An error state should be introduced as a part of the value type, which is specified using %value
.
I show an example below. Only zero-division error is implemented here.
%prefix "calc"
%value "calc_result_t"
%header {
typedef struct calc_result_tag {
int value;
int error; /* 0: no error, 1 error. */
} calc_result_t;
}
%source {
#include <stdio.h>
#include <stdlib.h>
static calc_result_t calc_result_new(int value, int error) {
calc_result_t r;
r.value = value;
r.error = error;
return r;
}
}
statement <- _ e:expression _ EOL { if (e.error) printf("arithmetic error\n"); else printf("answer=%d\n", e); }
/ ( !EOL . )* EOL { printf("syntax error\n"); }
expression <- e:term { $$ = e; }
term <- l:term _ '+' _ r:factor { $$ = calc_result_new(l.value + r.value, l.error | r.error); }
/ l:term _ '-' _ r:factor { $$ = calc_result_new(l.value - r.value, l.error | r.error); }
/ e:factor { $$ = e; }
factor <- l:factor _ '*' _ r:unary { $$ = calc_result_new(l.value * r.value, l.error | r.error); }
/ l:factor _ '/' _ r:unary { $$ = (r.value != 0) ? calc_result_new(l.value / r.value, l.error | r.error) : calc_result_new(0, 1); }
/ e:unary { $$ = e; }
unary <- '+' _ e:unary { $$ = e; }
/ '-' _ e:unary { $$ = calc_result_new(-e.value, e.error); }
/ e:primary { $$ = e; }
primary <- < [0-9]+ > { $$ = calc_result_new(atoi($1), 0); }
/ '(' _ e:expression _ ')' { $$ = e; }
_ <- [ \t]*
EOL <- '\n' / '\r\n' / '\r' / ';'
%%
int main() {
calc_context_t *ctx = calc_create(NULL);
while (calc_parse(ctx, NULL));
calc_destroy(ctx);
return 0;
}
thank you very much, that answers my question and is a great example. thank you so much for taking the time to enlighten me! you can close this issue.
It is unclear to me if it is possible to raise an error from the action. In your example calculator it would make sense for example for division by zero or (int_min / -1).
thank you for this awesome project!