Skip to content

Commit d72bae0

Browse files
committed
rest works
1 parent 4683c7a commit d72bae0

7 files changed

Lines changed: 322 additions & 19 deletions

File tree

BasicCalculator/calculator/calculator.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,30 @@
44
#include "internal/evaluator/evaluator.hpp"
55
#include "internal/shared/shared.hpp"
66

7+
using namespace calculator::internal;
8+
79
namespace calculator
810
{
911
double calculator_t::calculate(const std::string& equation)
1012
{
11-
lexer_t lexer{};
12-
std::vector<shared::token_t> tokens = lexer.tokenize(equation);
13+
try
14+
{
15+
lexer_t lexer{};
16+
std::vector<shared::token_t> tokens = lexer.tokenize(equation);
17+
18+
parser_t parser{};
19+
std::shared_ptr<shared::base_expr_t> main_stmt = parser.parse(tokens);
1320

14-
for (shared::token_t& token : tokens)
21+
evaluator_t evaluator{};
22+
double result = evaluator.eval(main_stmt);
23+
24+
return result;
25+
}
26+
catch (std::exception& except)
1527
{
16-
token.output();
28+
std::printf("Error: %s\n", except.what());
1729
}
1830

19-
return 69.6942069;
31+
return 0;
2032
}
2133
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "evaluator.hpp"
2+
#include <stdexcept>
3+
4+
using namespace calculator::internal;
5+
using shared::token_tt, shared::expr_tt;
6+
7+
namespace calculator
8+
{
9+
namespace internal
10+
{
11+
double evaluator_t::eval(std::shared_ptr<shared::base_expr_t> current)
12+
{
13+
switch (current->get_type())
14+
{
15+
case expr_tt::BINARY:
16+
{
17+
std::shared_ptr<shared::binary_expr_t> binary_expr = std::reinterpret_pointer_cast<shared::binary_expr_t>(current);
18+
switch (binary_expr->operation)
19+
{
20+
case token_tt::ADD:
21+
return this->eval(binary_expr->left) + this->eval(binary_expr->right);
22+
break;
23+
case token_tt::SUB:
24+
return this->eval(binary_expr->left) - this->eval(binary_expr->right);
25+
break;
26+
case token_tt::MUL:
27+
return this->eval(binary_expr->left) * this->eval(binary_expr->right);
28+
break;
29+
case token_tt::DIV:
30+
return this->eval(binary_expr->left) / this->eval(binary_expr->right);
31+
break;
32+
case token_tt::MOD:
33+
return fmod(this->eval(binary_expr->left), this->eval(binary_expr->right));
34+
break;
35+
case token_tt::POW:
36+
return pow(this->eval(binary_expr->left), this->eval(binary_expr->right));
37+
default:
38+
throw std::runtime_error("Unknown operation used!");
39+
break;
40+
}
41+
42+
break;
43+
}
44+
case expr_tt::NUMBER:
45+
{
46+
std::shared_ptr<shared::number_expr_t> number_expr = std::reinterpret_pointer_cast<shared::number_expr_t>(current);
47+
return number_expr->value;
48+
break;
49+
}
50+
case expr_tt::UNARY:
51+
{
52+
std::shared_ptr<shared::unary_expr_t> unary_expr = std::reinterpret_pointer_cast<shared::unary_expr_t>(current);
53+
return -this->eval(unary_expr->child);
54+
}
55+
default:
56+
throw std::runtime_error("Unexpected node to evaluate!");
57+
break;
58+
}
59+
}
60+
}
61+
}

BasicCalculator/calculator/internal/evaluator/evaluator.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#pragma once
2-
2+
#include "../shared/shared.hpp"
33

44
namespace calculator
55
{
@@ -10,6 +10,8 @@ namespace calculator
1010
public:
1111
evaluator_t() = default;
1212
evaluator_t(const evaluator_t&) = delete;
13+
14+
double eval(std::shared_ptr<shared::base_expr_t> expression);
1315
};
1416
}
15-
}
17+
}

BasicCalculator/calculator/internal/lexer/lexer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ std::vector<shared::token_t> lexer_t::tokenize(const std::string& value)
7070
case '^':
7171
operation = shared::token_tt::POW;
7272
break;
73+
case '(':
74+
operation = shared::token_tt::OPEN_PAREN;
75+
break;
76+
case ')':
77+
operation = shared::token_tt::CLOSE_PAREN;
78+
break;
7379
}
7480

7581
if (operation != shared::token_tt::NONE)
Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,192 @@
11
#include "parser.hpp"
2+
#include <stdexcept>
23

34
using namespace calculator::internal;
5+
using shared::token_tt;
46

5-
shared::base_expr_t parse(const std::vector<shared::token_t>& tokens)
7+
namespace calculator
68
{
9+
namespace internal
10+
{
11+
std::optional<shared::token_t> parser_t::eat_token()
12+
{
13+
if (current_index < tokens.size())
14+
return this->tokens[this->current_index++];
715

16+
return std::nullopt;
17+
}
18+
19+
std::optional<shared::token_t> parser_t::peak_token()
20+
{
21+
if (current_index < tokens.size())
22+
return this->tokens[this->current_index];
23+
24+
return std::nullopt;
25+
}
26+
27+
std::shared_ptr<shared::base_expr_t> parser_t::parse_primary()
28+
{
29+
if (auto token = this->eat_token())
30+
{
31+
switch (token->value)
32+
{
33+
case token_tt::NUMBER:
34+
{
35+
std::shared_ptr<shared::number_expr_t> number = std::make_shared<shared::number_expr_t>(token->number);
36+
return std::move(number);
37+
break;
38+
}
39+
default:
40+
token->output();
41+
throw std::runtime_error("Received invalid token!");
42+
break;
43+
}
44+
}
45+
else
46+
throw std::runtime_error("Expected primary token!");
47+
}
48+
49+
std::shared_ptr<shared::base_expr_t> parser_t::parse_paren()
50+
{
51+
std::shared_ptr<shared::base_expr_t> rtn_expr;
52+
53+
if (auto next_token = this->peak_token())
54+
{
55+
if (next_token->value == token_tt::OPEN_PAREN)
56+
{
57+
this->eat_token();
58+
rtn_expr = this->parse();
59+
next_token = this->peak_token();
60+
if (next_token && next_token->value == token_tt::CLOSE_PAREN)
61+
this->eat_token();
62+
else
63+
{
64+
throw std::runtime_error("Closing parenthesis expected!");
65+
}
66+
}
67+
}
68+
69+
if (rtn_expr.get() == nullptr)
70+
rtn_expr = parse_primary();
71+
72+
return rtn_expr;
73+
}
74+
75+
std::shared_ptr<shared::base_expr_t> parser_t::parse_unary()
76+
{
77+
std::shared_ptr<shared::base_expr_t> rtn_expr;
78+
79+
if (auto next_token = this->peak_token())
80+
{
81+
if (next_token->value == token_tt::SUB)
82+
{
83+
this->eat_token();
84+
std::shared_ptr<shared::base_expr_t> left_expr = parse_paren();
85+
rtn_expr = std::make_unique<shared::unary_expr_t>(std::move(left_expr));
86+
}
87+
}
88+
89+
if (rtn_expr.get() == nullptr)
90+
rtn_expr = parse_paren();
91+
92+
return rtn_expr;
93+
}
94+
95+
std::shared_ptr<shared::base_expr_t> parser_t::parse_powmod()
96+
{
97+
std::shared_ptr<shared::base_expr_t> rtn_expr;
98+
std::shared_ptr<shared::base_expr_t> left_expr = parse_unary();
99+
100+
if (auto next_token = this->peak_token())
101+
{
102+
while (next_token)
103+
{
104+
if (next_token->value == token_tt::MOD || next_token->value == token_tt::POW)
105+
{
106+
shared::token_t current = *this->eat_token();
107+
left_expr = std::make_unique<shared::binary_expr_t>(std::move(left_expr), this->parse_powmod(), current.value);
108+
rtn_expr = left_expr;
109+
}
110+
else
111+
break;
112+
113+
next_token = this->peak_token();
114+
}
115+
}
116+
117+
if (rtn_expr.get() == nullptr)
118+
rtn_expr = left_expr;
119+
120+
return rtn_expr;
121+
}
122+
123+
std::shared_ptr<shared::base_expr_t> parser_t::parse_muldiv()
124+
{
125+
std::shared_ptr<shared::base_expr_t> rtn_expr;
126+
std::shared_ptr<shared::base_expr_t> left_expr = parse_powmod();
127+
128+
if (auto next_token = this->peak_token())
129+
{
130+
while (next_token)
131+
{
132+
if (next_token->value == token_tt::MUL || next_token->value == token_tt::DIV)
133+
{
134+
shared::token_t current = *this->eat_token();
135+
left_expr = std::make_unique<shared::binary_expr_t>(std::move(left_expr), this->parse_muldiv(), current.value);
136+
rtn_expr = left_expr;
137+
}
138+
else
139+
break;
140+
141+
next_token = this->peak_token();
142+
}
143+
}
144+
145+
if (rtn_expr.get() == nullptr)
146+
rtn_expr = left_expr;
147+
148+
return rtn_expr;
149+
}
150+
151+
std::shared_ptr<shared::base_expr_t> parser_t::parse_addsub()
152+
{
153+
std::shared_ptr<shared::base_expr_t> rtn_expr;
154+
std::shared_ptr<shared::base_expr_t> left_expr = parse_muldiv();
155+
156+
if (auto next_token = this->peak_token())
157+
{
158+
while (next_token)
159+
{
160+
if (next_token->value == token_tt::ADD || next_token->value == token_tt::SUB)
161+
{
162+
shared::token_t current = *this->eat_token();
163+
left_expr = std::make_unique<shared::binary_expr_t>(std::move(left_expr), this->parse_addsub(), current.value);
164+
rtn_expr = left_expr;
165+
}
166+
else
167+
break;
168+
169+
next_token = this->peak_token();
170+
}
171+
}
172+
173+
if (rtn_expr.get() == nullptr)
174+
rtn_expr = left_expr;
175+
176+
return rtn_expr;
177+
}
178+
179+
std::shared_ptr<shared::base_expr_t> parser_t::parse()
180+
{
181+
return this->parse_addsub();
182+
}
183+
184+
std::shared_ptr<shared::base_expr_t> parser_t::parse(const std::vector<shared::token_t>& tokens)
185+
{
186+
this->tokens = tokens;
187+
this->current_index = 0;
188+
189+
return this->parse();
190+
}
191+
}
8192
}
Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <vector>
3+
#include <optional>
34
#include "../shared/shared.hpp"
45

56
namespace calculator
@@ -8,11 +9,25 @@ namespace calculator
89
{
910
class parser_t
1011
{
12+
private:
13+
std::size_t current_index = 0;
14+
std::vector<shared::token_t> tokens{};
15+
16+
std::optional<shared::token_t> eat_token();
17+
std::optional<shared::token_t> peak_token();
18+
19+
std::shared_ptr<shared::base_expr_t> parse_primary();
20+
std::shared_ptr<shared::base_expr_t> parse_paren();
21+
std::shared_ptr<shared::base_expr_t> parse_unary();
22+
std::shared_ptr<shared::base_expr_t> parse_powmod();
23+
std::shared_ptr<shared::base_expr_t> parse_muldiv();
24+
std::shared_ptr<shared::base_expr_t> parse_addsub();
25+
std::shared_ptr<shared::base_expr_t> parse();
1126
public:
1227
parser_t() = default;
1328
parser_t(const parser_t&) = delete;
1429

15-
shared::base_expr_t parse(const std::vector<shared::token_t>& tokens);
30+
std::shared_ptr<shared::base_expr_t> parse(const std::vector<shared::token_t>& tokens);
1631
};
1732
}
1833
}

0 commit comments

Comments
 (0)