aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/server/parser/operator.hpp
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2019-12-07 03:36:21 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2019-12-07 03:36:21 +0300
commit00863566ec4601c65c435b74e575d49546a1c707 (patch)
tree479a0a6e96aba8191c7a65ea9bee2f4d5e3a4aba /server/parser/operator.hpp
parentadd stress_test.py (diff)
downloadmath-server-00863566ec4601c65c435b74e575d49546a1c707.tar.gz
math-server-00863566ec4601c65c435b74e575d49546a1c707.zip
split server into multiple components
In a vague attempt to make header files more readable, split server/ into a number of components. Also, refactor the unit tests to use the "Data-driven test cases" of Boost.Test.
Diffstat (limited to '')
-rw-r--r--server/parser/operator.hpp79
1 files changed, 79 insertions, 0 deletions
diff --git a/server/parser/operator.hpp b/server/parser/operator.hpp
new file mode 100644
index 0000000..4226078
--- /dev/null
+++ b/server/parser/operator.hpp
@@ -0,0 +1,79 @@
+#pragma once
+
+#include "error.hpp"
+
+#include "../lexer/token.hpp"
+#include "../lexer/token_type.hpp"
+
+namespace math::server::parser {
+
+class BinaryOp {
+public:
+ using Token = lexer::Token;
+ using Type = Token::Type;
+
+ static bool is(const Token& token) {
+ switch (token.get_type()) {
+ case Type::PLUS:
+ case Type::MINUS:
+ case Type::ASTERISK:
+ case Type::SLASH:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ static BinaryOp from_token(const Token& token) {
+ if (!is(token)) {
+ throw ParserError{"internal: token is not a binary operator"};
+ }
+ return BinaryOp{token};
+ }
+
+ static constexpr unsigned min_precedence() { return 0; }
+
+ unsigned get_precedence() const {
+ switch (m_type) {
+ case Type::PLUS:
+ case Type::MINUS:
+ return min_precedence();
+
+ case Type::ASTERISK:
+ case Type::SLASH:
+ return min_precedence() + 1;
+
+ default:
+ throw ParserError{"internal: undefined operator precedence"};
+ }
+ }
+
+ double exec(double lhs, double rhs) const {
+ switch (m_type) {
+ case Type::PLUS:
+ return lhs + rhs;
+ case Type::MINUS:
+ return lhs - rhs;
+ case Type::ASTERISK:
+ return lhs * rhs;
+ case Type::SLASH:
+ // Trapping the CPU would be better?
+ if (rhs == 0.) {
+ throw ParserError{"division by zero"};
+ }
+ return lhs / rhs;
+ default:
+ throw ParserError{"internal: unsupported operator"};
+ }
+ }
+
+private:
+ explicit BinaryOp(const Token& token)
+ : m_type{token.get_type()}
+ { }
+
+ Type m_type;
+};
+
+}