aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/parser.cc')
-rw-r--r--src/google/protobuf/compiler/parser.cc80
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,