Also note that:
switch (expr->operator) {
case '+':
result = b->number + a->number;
break;
case '-':
result = b->number - a->number;
break;
case '/':
result = b->number / a->number;
break;
case '*':
result = b->number * a->number;
break;
case '^':
result = pow(b->number, a->number);
break;
}
all these operations can cause overflow, which would invoke undefined behavior. You might be interested in seeing: Checked integer arithmetic in the prospect of C23, namely these functions:
#include <stdckdint.h>
bool ckd_add(type1 *result, type2 a, type3 b);
bool ckd_sub(type1 *result, type2 a, type3 b);
bool ckd_mul(type1 *result, type2 a, type3 b);