blob: 70c01adf74ff2bbbb095889b52ad595e74c40e90 [file] [log] [blame]
Alexander Hansen4e1142d2025-07-25 17:07:27 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2017 Intel Corporation, 2022 IBM Corp.
Andrew Jefferya05437e2022-04-07 16:17:21 +09303
Brad Bishope45d8c72022-05-25 15:12:53 -04004#include "expression.hpp"
Andrew Jefferya05437e2022-04-07 16:17:21 +09305
Alexander Hansen8feb0452025-09-15 14:29:20 +02006#include <phosphor-logging/lg2.hpp>
7
Andrew Jefferya05437e2022-04-07 16:17:21 +09308#include <stdexcept>
9
10namespace expression
11{
12std::optional<Operation> parseOperation(std::string& op)
13{
14 if (op == "+")
15 {
16 return Operation::addition;
17 }
18 if (op == "-")
19 {
20 return Operation::subtraction;
21 }
22 if (op == "*")
23 {
24 return Operation::multiplication;
25 }
26 if (op == R"(%)")
27 {
28 return Operation::modulo;
29 }
30 if (op == R"(/)")
31 {
32 return Operation::division;
33 }
34
35 return std::nullopt;
36}
37
38int evaluate(int a, Operation op, int b)
39{
40 switch (op)
41 {
42 case Operation::addition:
43 {
44 return a + b;
45 }
46 case Operation::subtraction:
47 {
48 return a - b;
49 }
50 case Operation::multiplication:
51 {
52 return a * b;
53 }
54 case Operation::division:
55 {
V-Sanjana9e92c962023-01-19 20:41:39 +053056 if (b == 0)
57 {
58 throw std::runtime_error(
59 "Math error: Attempted to divide by Zero\n");
60 }
Andrew Jefferya05437e2022-04-07 16:17:21 +093061 return a / b;
62 }
63 case Operation::modulo:
64 {
P Dheeraj Srujan Kumar2eb6c6f2023-01-23 20:57:16 +053065 if (b == 0)
66 {
67 throw std::runtime_error(
68 "Math error: Attempted to divide by Zero\n");
69 }
Andrew Jefferya05437e2022-04-07 16:17:21 +093070 return a % b;
71 }
72
73 default:
74 throw std::invalid_argument("Unrecognised operation");
75 }
76}
Andrew Jeffery5ace4e42022-04-07 16:58:30 +093077
Andrew Jeffery95559612022-04-07 17:22:47 +093078int evaluate(int substitute, std::vector<std::string>::iterator curr,
79 std::vector<std::string>::iterator& end)
Andrew Jeffery5ace4e42022-04-07 16:58:30 +093080{
81 bool isOperator = true;
82 std::optional<Operation> next = Operation::addition;
83
84 for (; curr != end; curr++)
85 {
86 if (isOperator)
87 {
88 next = expression::parseOperation(*curr);
89 if (!next)
90 {
91 break;
92 }
93 }
94 else
95 {
96 try
97 {
98 int constant = std::stoi(*curr);
99 substitute = evaluate(substitute, *next, constant);
100 }
101 catch (const std::invalid_argument&)
102 {
Alexander Hansen8feb0452025-09-15 14:29:20 +0200103 lg2::error("Parameter not supported for templates {STR}", "STR",
104 *curr);
Andrew Jeffery5ace4e42022-04-07 16:58:30 +0930105 continue;
106 }
107 }
108 isOperator = !isOperator;
109 }
110
Andrew Jeffery95559612022-04-07 17:22:47 +0930111 end = curr;
Andrew Jeffery5ace4e42022-04-07 16:58:30 +0930112 return substitute;
113}
Andrew Jefferya05437e2022-04-07 16:17:21 +0930114} // namespace expression