diff options
Diffstat (limited to 'src/google/protobuf/compiler/parser.cc')
-rw-r--r-- | src/google/protobuf/compiler/parser.cc | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index c50cdf54..a2eeee2d 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -686,6 +686,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, LocationRecorder location(message_location, DescriptorProto::kExtensionRangeFieldNumber); return ParseExtensions(message, location, containing_file); + } else if (LookingAt("reserved")) { + return ParseReserved(message, message_location); } else if (LookingAt("extend")) { LocationRecorder location(message_location, DescriptorProto::kExtensionFieldNumber); @@ -733,6 +735,13 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, FieldDescriptorProto::Label label; if (ParseLabel(&label, containing_file)) { field->set_label(label); + if (label == FieldDescriptorProto::LABEL_OPTIONAL && + syntax_identifier_ == "proto3") { + AddError( + "Explicit 'optional' labels are disallowed in the Proto3 syntax. " + "To define 'optional' fields in Proto3, simply remove the " + "'optional' label, as fields are 'optional' by default."); + } } } @@ -1353,6 +1362,77 @@ bool Parser::ParseExtensions(DescriptorProto* message, return true; } +// This is similar to extension range parsing, except that "max" is not +// supported, and accepts field name literals. +bool Parser::ParseReserved(DescriptorProto* message, + const LocationRecorder& message_location) { + // Parse the declaration. + DO(Consume("reserved")); + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + LocationRecorder location(message_location, + DescriptorProto::kReservedNameFieldNumber); + return ParseReservedNames(message, location); + } else { + LocationRecorder location(message_location, + DescriptorProto::kReservedRangeFieldNumber); + return ParseReservedNumbers(message, location); + } +} + + +bool Parser::ParseReservedNames(DescriptorProto* message, + const LocationRecorder& parent_location) { + do { + LocationRecorder location(parent_location, message->reserved_name_size()); + DO(ConsumeString(message->add_reserved_name(), "Expected field name.")); + } while (TryConsume(",")); + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + +bool Parser::ParseReservedNumbers(DescriptorProto* message, + const LocationRecorder& parent_location) { + bool first = true; + do { + LocationRecorder location(parent_location, message->reserved_range_size()); + + DescriptorProto::ReservedRange* range = message->add_reserved_range(); + int start, end; + io::Tokenizer::Token start_token; + { + LocationRecorder start_location( + location, DescriptorProto::ReservedRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeInteger(&start, (first ? + "Expected field name or number range." : + "Expected field number range."))); + } + + if (TryConsume("to")) { + LocationRecorder end_location( + location, DescriptorProto::ReservedRange::kEndFieldNumber); + DO(ConsumeInteger(&end, "Expected integer.")); + } else { + LocationRecorder end_location( + location, DescriptorProto::ReservedRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); + end = start; + } + + // Users like to specify inclusive ranges, but in code we like the end + // number to be exclusive. + ++end; + + range->set_start(start); + range->set_end(end); + first = false; + } while (TryConsume(",")); + + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, RepeatedPtrField<DescriptorProto>* messages, const LocationRecorder& parent_location, |