diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2019-12-07 03:36:21 +0300 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2019-12-07 03:36:21 +0300 |
commit | 00863566ec4601c65c435b74e575d49546a1c707 (patch) | |
tree | 479a0a6e96aba8191c7a65ea9bee2f4d5e3a4aba /server/parser/operator.hpp | |
parent | add stress_test.py (diff) | |
download | math-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.hpp | 79 |
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; +}; + +} |