198 lines
3.4 KiB
Text
198 lines
3.4 KiB
Text
|
%{
|
||
|
#include <errno.h>
|
||
|
#include <limits.h>
|
||
|
#include <math.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
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
|
||
|
|
||
|
%%
|
||
|
<INITIAL>{
|
||
|
-?[[: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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
<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;
|
||
|
}
|