%{ #include #include #include #include #include #include typedef struct { int64_t value; bool exists; } Option; uint64_t allocated = 0; int64_t *bottom; int64_t *top; void reset(void) { top = bottom; } void push(int64_t x) { if (top >= bottom + allocated) { errno = 0; bottom = realloc(bottom, allocated * 2); if (errno == ENOMEM) { fprintf(stderr, "failed reallocating stack!\n"); exit(EXIT_FAILURE); } } *top = x; top += 1; } Option pop(void) { if (top == bottom) { printf("Błąd: za mała liczba argumentów\n"); reset(); return (Option){ .value = 0, .exists = false, }; } top -= 1; return (Option){ .value = *top, .exists = true, }; } %} %x ERROR %% { -?[[:digit:]]+ { errno = 0; int64_t x = strtoll(yytext, NULL, 10); if (errno == ERANGE) { if (x == LLONG_MIN) { printf("Błąd: zbyt mała liczba\n"); } else if (x == LLONG_MAX) { printf("Błąd: zbyt duża liczba\n"); } reset(); } else { push(x); } } "+" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push(y.value + x.value); } } "-" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push(y.value - x.value); } } "*" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push(y.value * x.value); } } "/" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push(y.value / x.value); } } "%" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push(y.value % x.value); } } "^" { Option x = pop(); Option y = pop(); if (!x.exists || !y.exists) { reset(); BEGIN(ERROR); } else { push((int64_t)powl((long double)y.value, (long double)x.value)); } } \n { if (top > bottom + 1) { printf("Błąd: za mała liczba operatorów\n"); reset(); } else { Option x = pop(); if (!x.exists) { reset(); BEGIN(ERROR); } else { printf("= %" PRId64 "\n", x.value); } } } [[:blank:]]+ {} . { printf("Błąd: zły symbol \"%s\"\n", yytext); reset(); BEGIN(ERROR); } } { \n { BEGIN(INITIAL); } . { } } %% int main(void) { allocated = 8; bottom = (int64_t *)malloc(allocated * sizeof(int64_t)); if (bottom == NULL) { fprintf(stderr, "failed allocating stack!\n"); return EXIT_FAILURE; } top = bottom; yylex(); free(bottom); return EXIT_SUCCESS; }