jftt/l2/4.lex
2024-11-03 22:14:31 +01:00

197 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;
}