From ccfb4c20bf4843b7025cff7f1c72f7066132b18e Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Tue, 19 Apr 2022 13:07:26 -0700 Subject: [PATCH] Handle +/-inf in protos (#7256) * Handle +/-inf in protos * Check for digit in 4th pos --- src/idl_parser.cpp | 34 +++++++++++++++++------ tests/prototest/test.golden | 3 ++ tests/prototest/test.proto | 4 +++ tests/prototest/test_include.golden | 3 ++ tests/prototest/test_suffix.golden | 3 ++ tests/prototest/test_union.golden | 3 ++ tests/prototest/test_union_include.golden | 3 ++ tests/prototest/test_union_suffix.golden | 3 ++ 8 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 489f913e2..74d61f3ef 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -489,10 +489,21 @@ CheckedError Parser::Next() { } const auto has_sign = (c == '+') || (c == '-'); - if (has_sign && IsIdentifierStart(*cursor_)) { - // '-'/'+' and following identifier - it could be a predefined - // constant. Return the sign in token_, see ParseSingleValue. - return NoError(); + if (has_sign) { + // Check for +/-inf which is considered a float constant. + if (strncmp(cursor_, "inf", 3) == 0 && + !(IsIdentifierStart(cursor_[4]) || is_digit(cursor_[4]))) { + attribute_.assign(cursor_ - 1, cursor_ + 3); + token_ = kTokenFloatConstant; + cursor_ += 3; + return NoError(); + } + + if (IsIdentifierStart(*cursor_)) { + // '-'/'+' and following identifier - it could be a predefined + // constant. Return the sign in token_, see ParseSingleValue. + return NoError(); + } } auto dot_lvl = @@ -2178,8 +2189,12 @@ template void EnumDef::ChangeEnumValue(EnumVal *ev, T new_value) { } namespace EnumHelper { -template struct EnumValType { typedef int64_t type; }; -template<> struct EnumValType { typedef uint64_t type; }; +template struct EnumValType { + typedef int64_t type; +}; +template<> struct EnumValType { + typedef uint64_t type; +}; } // namespace EnumHelper struct EnumValBuilder { @@ -2885,8 +2900,11 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, if (key == "default") { // Temp: skip non-numeric and non-boolean defaults (enums). auto numeric = strpbrk(val.c_str(), "0123456789-+."); - if (IsScalar(type.base_type) && - (numeric == val.c_str() || val == "inf" || val == "-inf")) { + if (IsFloat(type.base_type) && + (val == "inf" || val == "+inf" || val == "-inf")) { + // Prefer to be explicit with +inf. + field->value.constant = val == "inf" ? "+inf" : val; + } else if (IsScalar(type.base_type) && numeric == val.c_str()) { field->value.constant = val; } else if (val == "true") { field->value.constant = val; diff --git a/tests/prototest/test.golden b/tests/prototest/test.golden index eb10671b1..949a003d5 100644 --- a/tests/prototest/test.golden +++ b/tests/prototest/test.golden @@ -51,6 +51,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.ProtoMessage_.Anonymous0; outer_enum:proto.test.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.ProtoMessage_; diff --git a/tests/prototest/test.proto b/tests/prototest/test.proto index 10e45aff8..71ec8d51d 100644 --- a/tests/prototest/test.proto +++ b/tests/prototest/test.proto @@ -67,4 +67,8 @@ message ProtoMessage { OtherMessage t = 18; } optional ProtoEnum outer_enum = 33; + // Tests that `inf` and `+/-inf` can be parsed in proto options. + optional float u = 34 [default = inf]; + optional float v = 35 [default = +inf]; + optional float w = 36 [default = -inf]; } diff --git a/tests/prototest/test_include.golden b/tests/prototest/test_include.golden index 358c3f66e..b98de44fb 100644 --- a/tests/prototest/test_include.golden +++ b/tests/prototest/test_include.golden @@ -49,6 +49,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.ProtoMessage_.Anonymous0; outer_enum:proto.test.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.ProtoMessage_; diff --git a/tests/prototest/test_suffix.golden b/tests/prototest/test_suffix.golden index a99f80739..4ab2146c5 100644 --- a/tests/prototest/test_suffix.golden +++ b/tests/prototest/test_suffix.golden @@ -51,6 +51,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.test_namespace_suffix.ProtoMessage_.Anonymous0; outer_enum:proto.test.test_namespace_suffix.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.test_namespace_suffix.ProtoMessage_; diff --git a/tests/prototest/test_union.golden b/tests/prototest/test_union.golden index 3e6becdc6..241f3491b 100644 --- a/tests/prototest/test_union.golden +++ b/tests/prototest/test_union.golden @@ -61,6 +61,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.ProtoMessage_.RUnion; outer_enum:proto.test.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.ProtoMessage_; diff --git a/tests/prototest/test_union_include.golden b/tests/prototest/test_union_include.golden index abdb6e24e..1fdb2acbc 100644 --- a/tests/prototest/test_union_include.golden +++ b/tests/prototest/test_union_include.golden @@ -59,6 +59,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.ProtoMessage_.RUnion; outer_enum:proto.test.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.ProtoMessage_; diff --git a/tests/prototest/test_union_suffix.golden b/tests/prototest/test_union_suffix.golden index 6a240c090..2278edd2c 100644 --- a/tests/prototest/test_union_suffix.golden +++ b/tests/prototest/test_union_suffix.golden @@ -61,6 +61,9 @@ table ProtoMessage { /// doc comment for r. r:proto.test.test_namespace_suffix.ProtoMessage_.RUnion; outer_enum:proto.test.test_namespace_suffix.ProtoEnum; + u:float = +inf; + v:float = +inf; + w:float = -inf; } namespace proto.test.test_namespace_suffix.ProtoMessage_;