-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathformula.cpp
80 lines (67 loc) · 2.33 KB
/
formula.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include "formula.h"
#include "FormulaAST.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <sstream>
using namespace std::literals;
std::ostream& operator<<(std::ostream& output, FormulaError fe) {
output << fe.ToString();
return output;
}
namespace {
class Formula : public FormulaInterface {
public:
// Реализуйте следующие методы:
explicit Formula(std::string expression)
: ast_(ParseFormulaAST(expression)) {
}
Value Evaluate(const SheetInterface& sheet) const override {
try {
return ast_.Execute(GetCellTranslator_(sheet));
} catch (FormulaError& err){
return err;
}
}
std::string GetExpression() const override {
std::ostringstream out;
ast_.PrintFormula(out);
return out.str();
}
std::vector<Position> GetReferencedCells() const {
const auto list = ast_.GetCells();
return {list.begin(), list.end()};
}
private:
FormulaAST ast_;
// Формирует лямбда-функцию, которая вовзращает значение ячейки
// по ее позиции из таблицы sheet
CellTranclatorLambda GetCellTranslator_(const SheetInterface& sheet) const {
return [&sheet](const Position* pos){
if (!pos->IsValid()){
throw FormulaError(FormulaError::Category::Ref);
}
const CellInterface *cell = sheet.GetCell(*pos);
if (!cell){
return 0.0;
}
const auto cell_value = cell->GetValue();
if (std::holds_alternative<double>(cell_value)){
return std::get<double>(cell_value);
} else if (std::holds_alternative<std::string>(cell_value)){
try {
return std::stod(std::get<std::string>(cell_value));
} catch (...) {
throw FormulaError(FormulaError::Category::Value);
}
} else if (std::holds_alternative<FormulaError>(cell_value)) {
throw std::get<FormulaError>(cell_value);
}
return 0.0;
};
}
};
} // namespace
std::unique_ptr<FormulaInterface> ParseFormula(std::string expression) {
return std::make_unique<Formula>(expression);
}