1*59ef1e72SChristopher Meis /*
2*59ef1e72SChristopher Meis // Copyright (c) 2017 Intel Corporation
3*59ef1e72SChristopher Meis // Copyright (c) 2022 IBM Corp.
4*59ef1e72SChristopher Meis //
5*59ef1e72SChristopher Meis // Licensed under the Apache License, Version 2.0 (the "License");
6*59ef1e72SChristopher Meis // you may not use this file except in compliance with the License.
7*59ef1e72SChristopher Meis // You may obtain a copy of the License at
8*59ef1e72SChristopher Meis //
9*59ef1e72SChristopher Meis // http://www.apache.org/licenses/LICENSE-2.0
10*59ef1e72SChristopher Meis //
11*59ef1e72SChristopher Meis // Unless required by applicable law or agreed to in writing, software
12*59ef1e72SChristopher Meis // distributed under the License is distributed on an "AS IS" BASIS,
13*59ef1e72SChristopher Meis // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*59ef1e72SChristopher Meis // See the License for the specific language governing permissions and
15*59ef1e72SChristopher Meis // limitations under the License.
16*59ef1e72SChristopher Meis */
17*59ef1e72SChristopher Meis
18*59ef1e72SChristopher Meis #include "expression.hpp"
19*59ef1e72SChristopher Meis
20*59ef1e72SChristopher Meis #include <iostream>
21*59ef1e72SChristopher Meis #include <stdexcept>
22*59ef1e72SChristopher Meis
23*59ef1e72SChristopher Meis namespace expression
24*59ef1e72SChristopher Meis {
parseOperation(std::string & op)25*59ef1e72SChristopher Meis std::optional<Operation> parseOperation(std::string& op)
26*59ef1e72SChristopher Meis {
27*59ef1e72SChristopher Meis if (op == "+")
28*59ef1e72SChristopher Meis {
29*59ef1e72SChristopher Meis return Operation::addition;
30*59ef1e72SChristopher Meis }
31*59ef1e72SChristopher Meis if (op == "-")
32*59ef1e72SChristopher Meis {
33*59ef1e72SChristopher Meis return Operation::subtraction;
34*59ef1e72SChristopher Meis }
35*59ef1e72SChristopher Meis if (op == "*")
36*59ef1e72SChristopher Meis {
37*59ef1e72SChristopher Meis return Operation::multiplication;
38*59ef1e72SChristopher Meis }
39*59ef1e72SChristopher Meis if (op == R"(%)")
40*59ef1e72SChristopher Meis {
41*59ef1e72SChristopher Meis return Operation::modulo;
42*59ef1e72SChristopher Meis }
43*59ef1e72SChristopher Meis if (op == R"(/)")
44*59ef1e72SChristopher Meis {
45*59ef1e72SChristopher Meis return Operation::division;
46*59ef1e72SChristopher Meis }
47*59ef1e72SChristopher Meis
48*59ef1e72SChristopher Meis return std::nullopt;
49*59ef1e72SChristopher Meis }
50*59ef1e72SChristopher Meis
evaluate(int a,Operation op,int b)51*59ef1e72SChristopher Meis int evaluate(int a, Operation op, int b)
52*59ef1e72SChristopher Meis {
53*59ef1e72SChristopher Meis switch (op)
54*59ef1e72SChristopher Meis {
55*59ef1e72SChristopher Meis case Operation::addition:
56*59ef1e72SChristopher Meis {
57*59ef1e72SChristopher Meis return a + b;
58*59ef1e72SChristopher Meis }
59*59ef1e72SChristopher Meis case Operation::subtraction:
60*59ef1e72SChristopher Meis {
61*59ef1e72SChristopher Meis return a - b;
62*59ef1e72SChristopher Meis }
63*59ef1e72SChristopher Meis case Operation::multiplication:
64*59ef1e72SChristopher Meis {
65*59ef1e72SChristopher Meis return a * b;
66*59ef1e72SChristopher Meis }
67*59ef1e72SChristopher Meis case Operation::division:
68*59ef1e72SChristopher Meis {
69*59ef1e72SChristopher Meis if (b == 0)
70*59ef1e72SChristopher Meis {
71*59ef1e72SChristopher Meis throw std::runtime_error(
72*59ef1e72SChristopher Meis "Math error: Attempted to divide by Zero\n");
73*59ef1e72SChristopher Meis }
74*59ef1e72SChristopher Meis return a / b;
75*59ef1e72SChristopher Meis }
76*59ef1e72SChristopher Meis case Operation::modulo:
77*59ef1e72SChristopher Meis {
78*59ef1e72SChristopher Meis if (b == 0)
79*59ef1e72SChristopher Meis {
80*59ef1e72SChristopher Meis throw std::runtime_error(
81*59ef1e72SChristopher Meis "Math error: Attempted to divide by Zero\n");
82*59ef1e72SChristopher Meis }
83*59ef1e72SChristopher Meis return a % b;
84*59ef1e72SChristopher Meis }
85*59ef1e72SChristopher Meis
86*59ef1e72SChristopher Meis default:
87*59ef1e72SChristopher Meis throw std::invalid_argument("Unrecognised operation");
88*59ef1e72SChristopher Meis }
89*59ef1e72SChristopher Meis }
90*59ef1e72SChristopher Meis
evaluate(int substitute,std::vector<std::string>::iterator curr,std::vector<std::string>::iterator & end)91*59ef1e72SChristopher Meis int evaluate(int substitute, std::vector<std::string>::iterator curr,
92*59ef1e72SChristopher Meis std::vector<std::string>::iterator& end)
93*59ef1e72SChristopher Meis {
94*59ef1e72SChristopher Meis bool isOperator = true;
95*59ef1e72SChristopher Meis std::optional<Operation> next = Operation::addition;
96*59ef1e72SChristopher Meis
97*59ef1e72SChristopher Meis for (; curr != end; curr++)
98*59ef1e72SChristopher Meis {
99*59ef1e72SChristopher Meis if (isOperator)
100*59ef1e72SChristopher Meis {
101*59ef1e72SChristopher Meis next = expression::parseOperation(*curr);
102*59ef1e72SChristopher Meis if (!next)
103*59ef1e72SChristopher Meis {
104*59ef1e72SChristopher Meis break;
105*59ef1e72SChristopher Meis }
106*59ef1e72SChristopher Meis }
107*59ef1e72SChristopher Meis else
108*59ef1e72SChristopher Meis {
109*59ef1e72SChristopher Meis try
110*59ef1e72SChristopher Meis {
111*59ef1e72SChristopher Meis int constant = std::stoi(*curr);
112*59ef1e72SChristopher Meis substitute = evaluate(substitute, *next, constant);
113*59ef1e72SChristopher Meis }
114*59ef1e72SChristopher Meis catch (const std::invalid_argument&)
115*59ef1e72SChristopher Meis {
116*59ef1e72SChristopher Meis std::cerr << "Parameter not supported for templates " << *curr
117*59ef1e72SChristopher Meis << "\n";
118*59ef1e72SChristopher Meis continue;
119*59ef1e72SChristopher Meis }
120*59ef1e72SChristopher Meis }
121*59ef1e72SChristopher Meis isOperator = !isOperator;
122*59ef1e72SChristopher Meis }
123*59ef1e72SChristopher Meis
124*59ef1e72SChristopher Meis end = curr;
125*59ef1e72SChristopher Meis return substitute;
126*59ef1e72SChristopher Meis }
127*59ef1e72SChristopher Meis } // namespace expression
128