blob: 996e8219dc0b442c58e80fc2e40fa057ac1abeee [file] [log] [blame]
%token_type { double }
%left PLUS MINUS.
%left DIVIDE TIMES MOD.
%right POW NOT.
%include {
#include <assert.h>
#ifdef OS_WIN
#include <float.h>
#endif
#include <string.h>
#include <math.h>
namespace {
bool IsFinite(double x) {
#ifdef OS_WIN
return _finite(x);
#else
return isfinite(x);
#endif
}
} // anonymous namespace
#include "parser.h"
struct Result {
enum ErrorType {
NOT_ACCEPTED,
SYNTAX_ERROR,
DIVIDE_BY_ZERO,
STACK_OVERFLOW,
RESULT_OVERFLOW,
PARSE_ERROR,
UNKNOWN_ERROR,
ACCEPTED
};
double value;
ErrorType error_type;
Result() : value(0), error_type(NOT_ACCEPTED) {}
~Result() {}
void CheckValue(double val) {
if (!IsFinite(val)) {
error_type = RESULT_OVERFLOW;
}
}
};
}
%extra_argument { Result *result }
%parse_failure {
result->error_type = Result::PARSE_ERROR;
}
%stack_overflow {
result->error_type = Result::STACK_OVERFLOW;
}
%syntax_error {
result->error_type = Result::SYNTAX_ERROR;
}
%parse_accept {
if (result->error_type == Result::NOT_ACCEPTED) {
result->error_type = Result::ACCEPTED;
}
}
program ::= expr(A). {
if (result->error_type == Result::NOT_ACCEPTED &&
IsFinite(A)){
result->value = A;
} else {
result->error_type = Result::RESULT_OVERFLOW;
}
}
expr(A) ::= expr(B) MINUS expr(C). {
A = B - C;
result->CheckValue(A);
}
expr(A) ::= expr(B) PLUS expr(C). {
A = B + C;
result->CheckValue(A);
}
expr(A) ::= expr(B) TIMES expr(C). {
A = B * C;
result->CheckValue(A);
}
expr(A) ::= MINUS expr(B). [NOT] { A = - B; }
expr(A) ::= PLUS expr(B). [NOT] { A = B; }
expr(A) ::= expr(B) POW expr(C). {
A = pow(B, C);
result->CheckValue(A);
}
expr(A) ::= LP expr(B) RP. { A = B; }
expr(A) ::= expr(B) DIVIDE expr(C). {
if (C != 0.0) {
A = B / C;
result->CheckValue(A);
} else {
result->error_type = Result::DIVIDE_BY_ZERO;
}
}
expr(A) ::= expr(B) MOD expr(C). {
if (C != 0.0) {
A = fmod(B, C);
result->CheckValue(A);
} else {
result->error_type = Result::DIVIDE_BY_ZERO;
}
}
expr(A) ::= INTEGER(B). { A = B; }