| 214 | } |
| 215 | |
| 216 | bool MathParser::function1(Expression& expr) |
| 217 | { |
| 218 | static const std::vector<Func1> funcs { |
| 219 | { "floor", ::floor }, |
| 220 | { "ceil", ::ceil }, |
| 221 | { "round", ::round }, |
| 222 | { "abs", ::fabs }, |
| 223 | { "fabs", ::fabs }, |
| 224 | { "sqrt", ::sqrt }, |
| 225 | { "sin", ::sin }, |
| 226 | { "cos", ::cos }, |
| 227 | { "tan", ::tan }, |
| 228 | { "asin", ::asin }, |
| 229 | { "acos", ::acos }, |
| 230 | { "atan", ::atan }, |
| 231 | { "sinh", ::sinh }, |
| 232 | { "cosh", ::cosh }, |
| 233 | { "tanh", ::tanh }, |
| 234 | { "asinh", ::asinh }, |
| 235 | { "acosh", ::acosh }, |
| 236 | { "log", ::log }, |
| 237 | { "log2", ::log2 }, |
| 238 | { "log10", ::log10 }, |
| 239 | { "exp", ::exp }, |
| 240 | { "exp2", ::exp2 } |
| 241 | }; |
| 242 | |
| 243 | std::string name = curToken().sval(); |
| 244 | auto it = std::find_if(funcs.begin(), funcs.end(), |
| 245 | [&name](const Func1& f){ return f.name == name; }); |
| 246 | |
| 247 | if (it == funcs.end()) |
| 248 | { |
| 249 | if (peekToken() == TokenType::Lparen) |
| 250 | setError("Invalid function name '" + name + "'"); |
| 251 | return false; |
| 252 | } |
| 253 | |
| 254 | if (!match(TokenType::Lparen)) |
| 255 | { |
| 256 | setError("Expecting '(' to open function invocation of '" + name + "'."); |
| 257 | return false; |
| 258 | } |
| 259 | |
| 260 | if (!addexpr(expr)) |
| 261 | { |
| 262 | setError("Expecting expression following '" + name + "('."); |
| 263 | return false; |
| 264 | } |
| 265 | |
| 266 | if (!match(TokenType::Rparen)) |
| 267 | { |
| 268 | setError("Expecting ')' following '" + name + "' argument."); |
| 269 | return false; |
| 270 | } |
| 271 | |
| 272 | NodePtr sub = expr.popNode(); // Pop the primary. |
| 273 | expr.pushNode(NodePtr(new FuncNode(NodeType::Function, *it, std::move(sub)))); |