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