1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_ 18 #define LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_ 19 20 #include <string> 21 22 #include "utils/base/arena.h" 23 #include "utils/base/statusor.h" 24 #include "utils/grammar/semantics/eval-context.h" 25 #include "utils/grammar/semantics/evaluator.h" 26 #include "utils/grammar/semantics/expression_generated.h" 27 #include "utils/grammar/semantics/value.h" 28 #include "utils/strings/numbers.h" 29 30 namespace libtextclassifier3::grammar { 31 32 // Parses a string as a number. 33 class ParseNumberEvaluator : public SemanticExpressionEvaluator { 34 public: ParseNumberEvaluator(const SemanticExpressionEvaluator * composer)35 explicit ParseNumberEvaluator(const SemanticExpressionEvaluator* composer) 36 : composer_(composer) {} 37 Apply(const EvalContext & context,const SemanticExpression * expression,UnsafeArena * arena)38 StatusOr<const SemanticValue*> Apply(const EvalContext& context, 39 const SemanticExpression* expression, 40 UnsafeArena* arena) const override { 41 TC3_DCHECK_EQ(expression->expression_type(), 42 SemanticExpression_::Expression_ParseNumberExpression); 43 const ParseNumberExpression* parse_number_expression = 44 expression->expression_as_ParseNumberExpression(); 45 46 // Evaluate argument. 47 TC3_ASSIGN_OR_RETURN( 48 const SemanticValue* value, 49 composer_->Apply(context, parse_number_expression->value(), arena)); 50 if (value == nullptr) { 51 return nullptr; 52 } 53 if (!value->Has<StringPiece>()) { 54 return Status(StatusCode::INVALID_ARGUMENT, 55 "Argument didn't evaluate as a string value."); 56 } 57 const std::string data = value->Value<std::string>(); 58 59 // Parse the string data as a number. 60 const reflection::BaseType type = 61 static_cast<reflection::BaseType>(parse_number_expression->base_type()); 62 if (flatbuffers::IsLong(type)) { 63 TC3_ASSIGN_OR_RETURN(const int64 value, TryParse<int64>(data)); 64 return SemanticValue::Create(type, value, arena); 65 } else if (flatbuffers::IsInteger(type)) { 66 TC3_ASSIGN_OR_RETURN(const int32 value, TryParse<int32>(data)); 67 return SemanticValue::Create(type, value, arena); 68 } else if (flatbuffers::IsFloat(type)) { 69 TC3_ASSIGN_OR_RETURN(const double value, TryParse<double>(data)); 70 return SemanticValue::Create(type, value, arena); 71 } else { 72 return Status(StatusCode::INVALID_ARGUMENT, 73 "Unsupported type: " + std::to_string(type)); 74 } 75 } 76 77 private: 78 template <typename T> 79 bool Parse(const std::string& data, T* value) const; 80 81 template <> Parse(const std::string & data,int32 * value)82 bool Parse(const std::string& data, int32* value) const { 83 return ParseInt32(data.data(), value); 84 } 85 86 template <> Parse(const std::string & data,int64 * value)87 bool Parse(const std::string& data, int64* value) const { 88 return ParseInt64(data.data(), value); 89 } 90 91 template <> Parse(const std::string & data,double * value)92 bool Parse(const std::string& data, double* value) const { 93 return ParseDouble(data.data(), value); 94 } 95 96 template <typename T> TryParse(const std::string & data)97 StatusOr<T> TryParse(const std::string& data) const { 98 T result; 99 if (!Parse<T>(data, &result)) { 100 return Status(StatusCode::INVALID_ARGUMENT, "Could not parse value."); 101 } 102 return result; 103 } 104 105 const SemanticExpressionEvaluator* composer_; 106 }; 107 108 } // namespace libtextclassifier3::grammar 109 110 #endif // LIBTEXTCLASSIFIER_UTILS_GRAMMAR_SEMANTICS_EVALUATORS_PARSE_NUMBER_EVAL_H_ 111