1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright 2017 Intel Corporation, 2022 IBM Corp. 3 4 #include "expression.hpp" 5 6 #include <phosphor-logging/lg2.hpp> 7 8 #include <stdexcept> 9 10 namespace expression 11 { 12 std::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 38 int 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 { 56 if (b == 0) 57 { 58 throw std::runtime_error( 59 "Math error: Attempted to divide by Zero\n"); 60 } 61 return a / b; 62 } 63 case Operation::modulo: 64 { 65 if (b == 0) 66 { 67 throw std::runtime_error( 68 "Math error: Attempted to divide by Zero\n"); 69 } 70 return a % b; 71 } 72 73 default: 74 throw std::invalid_argument("Unrecognised operation"); 75 } 76 } 77 78 int evaluate(int substitute, std::vector<std::string>::iterator curr, 79 std::vector<std::string>::iterator& end) 80 { 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 { 103 lg2::error("Parameter not supported for templates {STR}", "STR", 104 *curr); 105 continue; 106 } 107 } 108 isOperator = !isOperator; 109 } 110 111 end = curr; 112 return substitute; 113 } 114 } // namespace expression 115