summaryrefslogtreecommitdiffstats
path: root/src/libixion/formula_tokens.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libixion/formula_tokens.cpp')
-rw-r--r--src/libixion/formula_tokens.cpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/src/libixion/formula_tokens.cpp b/src/libixion/formula_tokens.cpp
new file mode 100644
index 0000000..ea432e8
--- /dev/null
+++ b/src/libixion/formula_tokens.cpp
@@ -0,0 +1,303 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <ixion/formula_tokens.hpp>
+#include <ixion/exceptions.hpp>
+#include <ixion/global.hpp>
+#include <ixion/macros.hpp>
+
+#include <sstream>
+
+namespace ixion {
+
+std::string_view get_opcode_name(fopcode_t oc)
+{
+ // Make sure the names are ordered identically to the ordering of the enum members.
+ static constexpr std::string_view names[] = {
+ "unknown", // fop_unknown
+ "single-ref", // fop_single_ref
+ "range-ref", // fop_range_ref
+ "table-ref", // fop_table_ref
+ "named-expression", // fop_named_expression
+ "string", // fop_string
+ "value", // fop_value
+ "function", // fop_function
+ "plus", // fop_plus
+ "minus", // fop_minus
+ "divide", // fop_divide
+ "multiply", // fop_multiply
+ "exponent", // fop_exponent
+ "concat", // fop_concat
+ "equal", // fop_equal
+ "not-equal", // fop_not_equal
+ "less", // fop_less
+ "greater", // fop_greater
+ "less-equal", // fop_less_equal
+ "greater-equal", // fop_greater_equal
+ "open", // fop_open
+ "close", // fop_close
+ "sep", // fop_sep
+ "array-row-sep", // fop_array_row_sep
+ "array-open", // fop_array_open
+ "array-close", // fop_array_close
+ "error", // fop_error
+ };
+
+ if (std::size_t(oc) >= std::size(names))
+ return "???";
+
+ return names[oc];
+}
+
+std::string_view get_formula_opcode_string(fopcode_t oc)
+{
+ static constexpr std::string_view empty = "";
+
+ // Make sure the names are ordered identically to the ordering of the enum members.
+ static constexpr std::string_view names[] = {
+ empty, // fop_unknown
+ empty, // fop_single_ref
+ empty, // fop_range_ref
+ empty, // fop_table_ref
+ empty, // fop_named_expression
+ empty, // fop_string
+ empty, // fop_value
+ empty, // fop_function
+ "+", // fop_plus
+ "-", // fop_minus
+ "/", // fop_divide
+ "*", // fop_multiply
+ "^", // fop_exponent
+ "&", // fop_concat
+ "=", // fop_equal
+ "<>", // fop_not_equal
+ "<", // fop_less
+ ">", // fop_greater
+ "<=", // fop_less_equal
+ ">=", // fop_greater_equal
+ "(", // fop_open
+ ")", // fop_close
+ empty, // fop_sep
+ empty, // fop_array_row_sep
+ "{", // fop_array_open
+ "}", // fop_array_close
+ empty, // fop_error
+ };
+
+ if (std::size_t(oc) >= std::size(names))
+ return empty;
+
+ return names[oc];
+}
+
+// ============================================================================
+
+formula_token::formula_token(fopcode_t op) :
+ opcode(op)
+{
+ switch (opcode)
+ {
+ case fop_single_ref:
+ case fop_range_ref:
+ case fop_table_ref:
+ case fop_named_expression:
+ case fop_string:
+ case fop_value:
+ case fop_function:
+ {
+ std::ostringstream os;
+ os << "this opcode named '" << get_opcode_name(op) << "' cannot be instantiated by this constructor";
+ throw std::invalid_argument(os.str());
+ }
+ default:;
+ }
+}
+
+formula_token::formula_token(const address_t& addr) :
+ opcode(fop_single_ref), value(addr)
+{
+}
+
+formula_token::formula_token(const range_t& range) :
+ opcode(fop_range_ref), value(range)
+{
+}
+
+formula_token::formula_token(const table_t& table) :
+ opcode(fop_table_ref), value(table)
+{
+}
+
+formula_token::formula_token(formula_function_t func) :
+ opcode(fop_function), value(func)
+{
+}
+
+formula_token::formula_token(double v) :
+ opcode(fop_value), value(v)
+{
+}
+
+formula_token::formula_token(string_id_t sid) :
+ opcode(fop_string), value(sid)
+{
+}
+
+formula_token::formula_token(std::string name) :
+ opcode(fop_named_expression), value(std::move(name))
+{
+}
+
+
+formula_token::formula_token(const formula_token& r) = default;
+formula_token::formula_token(formula_token&& r) = default;
+formula_token::~formula_token() = default;
+
+bool formula_token::operator== (const formula_token& r) const
+{
+ return opcode == r.opcode && value == r.value;
+}
+
+bool formula_token::operator!= (const formula_token& r) const
+{
+ return !operator== (r);
+}
+
+struct formula_tokens_store::impl
+{
+ formula_tokens_t m_tokens;
+ size_t m_refcount;
+
+ impl() : m_refcount(0) {}
+};
+
+formula_tokens_store::formula_tokens_store() :
+ mp_impl(std::make_unique<impl>())
+{
+}
+
+formula_tokens_store::~formula_tokens_store()
+{
+}
+
+formula_tokens_store_ptr_t formula_tokens_store::create()
+{
+ return formula_tokens_store_ptr_t(new formula_tokens_store);
+}
+
+void formula_tokens_store::add_ref()
+{
+ ++mp_impl->m_refcount;
+}
+
+void formula_tokens_store::release_ref()
+{
+ if (--mp_impl->m_refcount == 0)
+ delete this;
+}
+
+size_t formula_tokens_store::get_reference_count() const
+{
+ return mp_impl->m_refcount;
+}
+
+formula_tokens_t& formula_tokens_store::get()
+{
+ return mp_impl->m_tokens;
+}
+
+const formula_tokens_t& formula_tokens_store::get() const
+{
+ return mp_impl->m_tokens;
+}
+
+named_expression_t::named_expression_t() {}
+named_expression_t::named_expression_t(const abs_address_t& _origin, formula_tokens_t _tokens) :
+ origin(_origin), tokens(std::move(_tokens)) {}
+
+named_expression_t::named_expression_t(named_expression_t&& other) :
+ origin(other.origin), tokens(std::move(other.tokens)) {}
+
+named_expression_t::~named_expression_t() {}
+
+std::ostream& operator<< (std::ostream& os, const formula_token& ft)
+{
+ switch (ft.opcode)
+ {
+ case fop_string:
+ {
+ os << "string token: (identifier=" << std::get<string_id_t>(ft.value) << ")";
+ break;
+ }
+ case fop_value:
+ {
+ os << "value token: " << std::get<double>(ft.value);
+ break;
+ }
+ case fop_single_ref:
+ {
+ os << "single ref token: " << std::get<address_t>(ft.value);
+ break;
+ }
+ case fop_range_ref:
+ {
+ os << "range ref token: " << std::get<range_t>(ft.value);
+ break;
+ }
+ case fop_table_ref:
+ {
+ os << "table ref token: " << std::get<table_t>(ft.value);
+ break;
+ }
+ case fop_named_expression:
+ {
+ os << "named expression token: '" << std::get<std::string>(ft.value) << "'";
+ break;
+ }
+ case fop_function:
+ {
+ using _int_type = std::underlying_type_t<formula_function_t>;
+
+ formula_function_t v = std::get<formula_function_t>(ft.value);
+ os << "function token: (opcode=" << _int_type(v) << "; name='" << get_formula_function_name(v) << "')";
+ break;
+ }
+ case fop_error:
+ {
+ os << "invalid error token: (count=" << std::get<string_id_t>(ft.value) << ")";
+ break;
+ }
+ case fop_plus:
+ case fop_minus:
+ case fop_divide:
+ case fop_multiply:
+ case fop_exponent:
+ case fop_concat:
+ case fop_equal:
+ case fop_not_equal:
+ case fop_less:
+ case fop_greater:
+ case fop_less_equal:
+ case fop_greater_equal:
+ case fop_open:
+ case fop_close:
+ case fop_sep:
+ case fop_array_row_sep:
+ case fop_array_open:
+ case fop_array_close:
+ case fop_unknown:
+ os << "opcode token: (name=" << get_opcode_name(ft.opcode) << "; s='"
+ << get_formula_opcode_string(ft.opcode) << "')";
+ break;
+ }
+
+ return os;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */