| 176 | } |
| 177 | |
| 178 | bool ConditionalParser::function1(Expression& expr) |
| 179 | { |
| 180 | auto checkMax = [](double d) -> bool |
| 181 | { |
| 182 | return d == (std::numeric_limits<double>::max)(); |
| 183 | }; |
| 184 | |
| 185 | auto checkMin = [](double d) -> bool |
| 186 | { |
| 187 | return d == (std::numeric_limits<double>::lowest)(); |
| 188 | }; |
| 189 | |
| 190 | auto checkNan = [](double d) -> bool |
| 191 | { |
| 192 | return std::isnan(d); |
| 193 | }; |
| 194 | |
| 195 | static const std::vector<BoolFunc1> funcs { |
| 196 | { "isnan", checkNan }, |
| 197 | { "ismax", checkMax }, |
| 198 | { "ismin", checkMin } |
| 199 | }; |
| 200 | |
| 201 | std::string name = peekToken().sval(); |
| 202 | auto it = std::find_if(funcs.begin(), funcs.end(), |
| 203 | [&name](const BoolFunc1& f){ return f.name == name; }); |
| 204 | |
| 205 | if (it == funcs.end()) |
| 206 | return false; |
| 207 | |
| 208 | match(TokenType::Identifier); // Move past identifier token. Guaranteed to work. |
| 209 | |
| 210 | if (!match(TokenType::Lparen)) |
| 211 | { |
| 212 | setError("Expecting '(' to open function invocation of '" + name + "'."); |
| 213 | return false; |
| 214 | } |
| 215 | |
| 216 | if (!addexpr(expr)) |
| 217 | return false; |
| 218 | |
| 219 | if (!match(TokenType::Rparen)) |
| 220 | { |
| 221 | setError("Expecting ')' following '" + name + "' argument."); |
| 222 | return false; |
| 223 | } |
| 224 | |
| 225 | NodePtr sub = expr.popNode(); // Pop the value expression. |
| 226 | expr.pushNode(NodePtr(new BoolFuncNode(NodeType::Function, *it, std::move(sub)))); |
| 227 | return true; |
| 228 | } |
| 229 | |
| 230 | } // namespace expr |
| 231 | } // namespace pdal |