-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProcessor.cpp
More file actions
120 lines (111 loc) · 4.19 KB
/
Processor.cpp
File metadata and controls
120 lines (111 loc) · 4.19 KB
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "Processor.h"
#include "Level.h"
#include <iostream>
#include <stdexcept>
namespace cmd_calc {
const double Processor::run() {
Level* curr = nullptr;
auto chit = std::begin(m_line);
do {
switch_char(chit);
++chit;
if (!m_value.empty() && (m_oper || chit == std::end(m_line))) {
Level* lev = new Level(std::stod(m_value), m_oper, m_prior, curr);
if (curr) {
curr->next = lev;
curr = curr->next;
} else curr = lev;
while (curr->prev && (
curr->prev->GetPriority() > curr->GetPriority() ||
curr->prev->GetPriority() == curr->GetPriority())) {
curr = curr->prev;
curr->exec();
}
flush();
}
} while (chit != std::end(m_line));
if (!curr) throw std::domain_error("invalid expression");
else return curr->GetValue();
}
void Processor::switch_char(const std::string::iterator chit) {
const char ch = *chit;
if (std::isdigit(ch)) {
if (is_valid_digit()) {
m_value.push_back(ch);
m_last = eDIGIT;
} else {
std::cout << "Digit '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected digit");
}
} else if (is_point(ch)) {
if (is_valid_point()) {
m_value.push_back(ch);
m_last = ePOINT;
} else {
std::cout << "Point symbol '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected point symbol");
}
} else if (is_oper(ch)) {
if (is_valid_oper()) {
m_oper = ch;
m_prior = m_bprior + sc_priorities.at(ch);
m_last = eOPER;
} else {
std::cout << "Operator '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected operator");
}
} else if (is_lb(ch)) {
if (is_valid_lb()) {
m_bprior += sc_bracket_weight;
m_last = eLB;
} else {
std::cout << "Bracket symbol '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected left bracket");
}
} else if (is_rb(ch)) {
if (is_valid_rb()) {
m_bprior -= sc_bracket_weight;
m_last = eRB;
} else {
std::cout << "Bracket symbol '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected right bracket");
}
} else if (std::isspace(ch)) {
} else {
std::cout << "Unknown symbol '" << ch << "' on pos " << chit - std::begin(m_line) << std::endl;
throw std::domain_error("unexpected symbol");
}
}
void Processor::flush() {
m_value.clear();
m_oper = 0;
m_prior = -1;
}
inline bool Processor::is_point(const char ch) {
return ch == '.';
}
inline bool Processor::is_oper(const char ch) {
return sc_priorities.count(ch);
}
inline bool Processor::is_lb(const char ch) {
return ch == '(';
}
inline bool Processor::is_rb(const char ch) {
return ch == ')';
}
inline bool Processor::is_valid_digit() {
return m_last != eRB;
}
inline bool Processor::is_valid_point() {
return m_last == eDIGIT;
}
inline bool Processor::is_valid_oper() {
return m_last == eDIGIT || m_last == eRB;
}
inline bool Processor::is_valid_lb() {
return m_last != eDIGIT && m_last != ePOINT && m_last != eRB;
}
inline bool Processor::is_valid_rb() {
return (m_last == eDIGIT || m_last == eRB) && m_bprior - sc_bracket_weight >= 0;
}
};