blob: 5c7047a631922c40a703f20af79b3682fe5d92fb [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: kenton@google.com (Kenton Varda)
32// Based on original Protocol Buffers design by
33// Sanjay Ghemawat, Jeff Dean, and others.
34//
35// Recursive descent FTW.
36
37#include <float.h>
38#include <google/protobuf/stubs/hash.h>
39#include <limits>
40
41
Austin Schuh40c16522018-10-28 20:27:54 -070042#include <google/protobuf/stubs/casts.h>
Brian Silverman9c614bc2016-02-15 20:20:02 -050043#include <google/protobuf/stubs/logging.h>
44#include <google/protobuf/stubs/common.h>
Austin Schuh40c16522018-10-28 20:27:54 -070045#include <google/protobuf/compiler/parser.h>
46#include <google/protobuf/descriptor.pb.h>
47#include <google/protobuf/io/tokenizer.h>
48#include <google/protobuf/descriptor.h>
49#include <google/protobuf/wire_format.h>
Brian Silverman9c614bc2016-02-15 20:20:02 -050050#include <google/protobuf/stubs/strutil.h>
51#include <google/protobuf/stubs/map_util.h>
52
53namespace google {
54namespace protobuf {
55namespace compiler {
56
57using internal::WireFormat;
58
59namespace {
60
61typedef hash_map<string, FieldDescriptorProto::Type> TypeNameMap;
62
63TypeNameMap MakeTypeNameTable() {
64 TypeNameMap result;
65
66 result["double" ] = FieldDescriptorProto::TYPE_DOUBLE;
67 result["float" ] = FieldDescriptorProto::TYPE_FLOAT;
68 result["uint64" ] = FieldDescriptorProto::TYPE_UINT64;
69 result["fixed64" ] = FieldDescriptorProto::TYPE_FIXED64;
70 result["fixed32" ] = FieldDescriptorProto::TYPE_FIXED32;
71 result["bool" ] = FieldDescriptorProto::TYPE_BOOL;
72 result["string" ] = FieldDescriptorProto::TYPE_STRING;
73 result["group" ] = FieldDescriptorProto::TYPE_GROUP;
74
75 result["bytes" ] = FieldDescriptorProto::TYPE_BYTES;
76 result["uint32" ] = FieldDescriptorProto::TYPE_UINT32;
77 result["sfixed32"] = FieldDescriptorProto::TYPE_SFIXED32;
78 result["sfixed64"] = FieldDescriptorProto::TYPE_SFIXED64;
79 result["int32" ] = FieldDescriptorProto::TYPE_INT32;
80 result["int64" ] = FieldDescriptorProto::TYPE_INT64;
81 result["sint32" ] = FieldDescriptorProto::TYPE_SINT32;
82 result["sint64" ] = FieldDescriptorProto::TYPE_SINT64;
83
84 return result;
85}
86
87const TypeNameMap kTypeNames = MakeTypeNameTable();
88
89// Camel-case the field name and append "Entry" for generated map entry name.
90// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
91string MapEntryName(const string& field_name) {
92 string result;
93 static const char kSuffix[] = "Entry";
94 result.reserve(field_name.size() + sizeof(kSuffix));
95 bool cap_next = true;
96 for (int i = 0; i < field_name.size(); ++i) {
97 if (field_name[i] == '_') {
98 cap_next = true;
99 } else if (cap_next) {
100 // Note: Do not use ctype.h due to locales.
101 if ('a' <= field_name[i] && field_name[i] <= 'z') {
102 result.push_back(field_name[i] - 'a' + 'A');
103 } else {
104 result.push_back(field_name[i]);
105 }
106 cap_next = false;
107 } else {
108 result.push_back(field_name[i]);
109 }
110 }
111 result.append(kSuffix);
112 return result;
113}
114
115} // anonymous namespace
116
117// Makes code slightly more readable. The meaning of "DO(foo)" is
118// "Execute foo and fail if it fails.", where failure is indicated by
119// returning false.
120#define DO(STATEMENT) if (STATEMENT) {} else return false
121
122// ===================================================================
123
124Parser::Parser()
125 : input_(NULL),
126 error_collector_(NULL),
127 source_location_table_(NULL),
128 had_errors_(false),
129 require_syntax_identifier_(false),
130 stop_after_syntax_identifier_(false) {
131}
132
133Parser::~Parser() {
134}
135
136// ===================================================================
137
138inline bool Parser::LookingAt(const char* text) {
139 return input_->current().text == text;
140}
141
142inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) {
143 return input_->current().type == token_type;
144}
145
146inline bool Parser::AtEnd() {
147 return LookingAtType(io::Tokenizer::TYPE_END);
148}
149
150bool Parser::TryConsume(const char* text) {
151 if (LookingAt(text)) {
152 input_->Next();
153 return true;
154 } else {
155 return false;
156 }
157}
158
159bool Parser::Consume(const char* text, const char* error) {
160 if (TryConsume(text)) {
161 return true;
162 } else {
163 AddError(error);
164 return false;
165 }
166}
167
168bool Parser::Consume(const char* text) {
169 if (TryConsume(text)) {
170 return true;
171 } else {
172 AddError("Expected \"" + string(text) + "\".");
173 return false;
174 }
175}
176
177bool Parser::ConsumeIdentifier(string* output, const char* error) {
178 if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
179 *output = input_->current().text;
180 input_->Next();
181 return true;
182 } else {
183 AddError(error);
184 return false;
185 }
186}
187
188bool Parser::ConsumeInteger(int* output, const char* error) {
189 if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
190 uint64 value = 0;
191 if (!io::Tokenizer::ParseInteger(input_->current().text,
192 kint32max, &value)) {
193 AddError("Integer out of range.");
194 // We still return true because we did, in fact, parse an integer.
195 }
196 *output = value;
197 input_->Next();
198 return true;
199 } else {
200 AddError(error);
201 return false;
202 }
203}
204
205bool Parser::ConsumeSignedInteger(int* output, const char* error) {
206 bool is_negative = false;
207 uint64 max_value = kint32max;
208 if (TryConsume("-")) {
209 is_negative = true;
210 max_value += 1;
211 }
212 uint64 value = 0;
213 DO(ConsumeInteger64(max_value, &value, error));
214 if (is_negative) value *= -1;
215 *output = value;
216 return true;
217}
218
219bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
220 const char* error) {
221 if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
222 if (!io::Tokenizer::ParseInteger(input_->current().text, max_value,
223 output)) {
224 AddError("Integer out of range.");
225 // We still return true because we did, in fact, parse an integer.
226 *output = 0;
227 }
228 input_->Next();
229 return true;
230 } else {
231 AddError(error);
232 return false;
233 }
234}
235
236bool Parser::ConsumeNumber(double* output, const char* error) {
237 if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
238 *output = io::Tokenizer::ParseFloat(input_->current().text);
239 input_->Next();
240 return true;
241 } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
242 // Also accept integers.
243 uint64 value = 0;
244 if (!io::Tokenizer::ParseInteger(input_->current().text,
245 kuint64max, &value)) {
246 AddError("Integer out of range.");
247 // We still return true because we did, in fact, parse a number.
248 }
249 *output = value;
250 input_->Next();
251 return true;
252 } else if (LookingAt("inf")) {
Austin Schuh40c16522018-10-28 20:27:54 -0700253 *output = std::numeric_limits<double>::infinity();
Brian Silverman9c614bc2016-02-15 20:20:02 -0500254 input_->Next();
255 return true;
256 } else if (LookingAt("nan")) {
Austin Schuh40c16522018-10-28 20:27:54 -0700257 *output = std::numeric_limits<double>::quiet_NaN();
Brian Silverman9c614bc2016-02-15 20:20:02 -0500258 input_->Next();
259 return true;
260 } else {
261 AddError(error);
262 return false;
263 }
264}
265
266bool Parser::ConsumeString(string* output, const char* error) {
267 if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
268 io::Tokenizer::ParseString(input_->current().text, output);
269 input_->Next();
270 // Allow C++ like concatenation of adjacent string tokens.
271 while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
272 io::Tokenizer::ParseStringAppend(input_->current().text, output);
273 input_->Next();
274 }
275 return true;
276 } else {
277 AddError(error);
278 return false;
279 }
280}
281
282bool Parser::TryConsumeEndOfDeclaration(
283 const char* text, const LocationRecorder* location) {
284 if (LookingAt(text)) {
285 string leading, trailing;
Austin Schuh40c16522018-10-28 20:27:54 -0700286 std::vector<string> detached;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500287 input_->NextWithComments(&trailing, &detached, &leading);
288
289 // Save the leading comments for next time, and recall the leading comments
290 // from last time.
291 leading.swap(upcoming_doc_comments_);
292
293 if (location != NULL) {
294 upcoming_detached_comments_.swap(detached);
295 location->AttachComments(&leading, &trailing, &detached);
296 } else if (strcmp(text, "}") == 0) {
297 // If the current location is null and we are finishing the current scope,
298 // drop pending upcoming detached comments.
299 upcoming_detached_comments_.swap(detached);
300 } else {
301 // Otherwise, append the new detached comments to the existing upcoming
302 // detached comments.
303 upcoming_detached_comments_.insert(upcoming_detached_comments_.end(),
304 detached.begin(), detached.end());
305 }
306
307 return true;
308 } else {
309 return false;
310 }
311}
312
313bool Parser::ConsumeEndOfDeclaration(
314 const char* text, const LocationRecorder* location) {
315 if (TryConsumeEndOfDeclaration(text, location)) {
316 return true;
317 } else {
318 AddError("Expected \"" + string(text) + "\".");
319 return false;
320 }
321}
322
323// -------------------------------------------------------------------
324
325void Parser::AddError(int line, int column, const string& error) {
326 if (error_collector_ != NULL) {
327 error_collector_->AddError(line, column, error);
328 }
329 had_errors_ = true;
330}
331
332void Parser::AddError(const string& error) {
333 AddError(input_->current().line, input_->current().column, error);
334}
335
336// -------------------------------------------------------------------
337
338Parser::LocationRecorder::LocationRecorder(Parser* parser)
339 : parser_(parser),
Austin Schuh40c16522018-10-28 20:27:54 -0700340 source_code_info_(parser->source_code_info_),
Brian Silverman9c614bc2016-02-15 20:20:02 -0500341 location_(parser_->source_code_info_->add_location()) {
342 location_->add_span(parser_->input_->current().line);
343 location_->add_span(parser_->input_->current().column);
344}
345
346Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) {
Austin Schuh40c16522018-10-28 20:27:54 -0700347 Init(parent, parent.source_code_info_);
348}
349
350Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
351 int path1,
352 SourceCodeInfo* source_code_info) {
353 Init(parent, source_code_info);
354 AddPath(path1);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500355}
356
357Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
358 int path1) {
Austin Schuh40c16522018-10-28 20:27:54 -0700359 Init(parent, parent.source_code_info_);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500360 AddPath(path1);
361}
362
363Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent,
364 int path1, int path2) {
Austin Schuh40c16522018-10-28 20:27:54 -0700365 Init(parent, parent.source_code_info_);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500366 AddPath(path1);
367 AddPath(path2);
368}
369
Austin Schuh40c16522018-10-28 20:27:54 -0700370void Parser::LocationRecorder::Init(const LocationRecorder& parent,
371 SourceCodeInfo* source_code_info) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500372 parser_ = parent.parser_;
Austin Schuh40c16522018-10-28 20:27:54 -0700373 source_code_info_ = source_code_info;
374
375 location_ = source_code_info_->add_location();
Brian Silverman9c614bc2016-02-15 20:20:02 -0500376 location_->mutable_path()->CopyFrom(parent.location_->path());
377
378 location_->add_span(parser_->input_->current().line);
379 location_->add_span(parser_->input_->current().column);
380}
381
382Parser::LocationRecorder::~LocationRecorder() {
383 if (location_->span_size() <= 2) {
384 EndAt(parser_->input_->previous());
385 }
386}
387
388void Parser::LocationRecorder::AddPath(int path_component) {
389 location_->add_path(path_component);
390}
391
392void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) {
393 location_->set_span(0, token.line);
394 location_->set_span(1, token.column);
395}
396
397void Parser::LocationRecorder::StartAt(const LocationRecorder& other) {
398 location_->set_span(0, other.location_->span(0));
399 location_->set_span(1, other.location_->span(1));
400}
401
402void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) {
403 if (token.line != location_->span(0)) {
404 location_->add_span(token.line);
405 }
406 location_->add_span(token.end_column);
407}
408
409void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor,
410 DescriptorPool::ErrorCollector::ErrorLocation location) {
411 if (parser_->source_location_table_ != NULL) {
412 parser_->source_location_table_->Add(
413 descriptor, location, location_->span(0), location_->span(1));
414 }
415}
416
Austin Schuh40c16522018-10-28 20:27:54 -0700417int Parser::LocationRecorder::CurrentPathSize() const {
418 return location_->path_size();
419}
420
Brian Silverman9c614bc2016-02-15 20:20:02 -0500421void Parser::LocationRecorder::AttachComments(
422 string* leading, string* trailing,
Austin Schuh40c16522018-10-28 20:27:54 -0700423 std::vector<string>* detached_comments) const {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500424 GOOGLE_CHECK(!location_->has_leading_comments());
425 GOOGLE_CHECK(!location_->has_trailing_comments());
426
427 if (!leading->empty()) {
428 location_->mutable_leading_comments()->swap(*leading);
429 }
430 if (!trailing->empty()) {
431 location_->mutable_trailing_comments()->swap(*trailing);
432 }
433 for (int i = 0; i < detached_comments->size(); ++i) {
434 location_->add_leading_detached_comments()->swap(
435 (*detached_comments)[i]);
436 }
437 detached_comments->clear();
438}
439
440// -------------------------------------------------------------------
441
442void Parser::SkipStatement() {
443 while (true) {
444 if (AtEnd()) {
445 return;
446 } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
447 if (TryConsumeEndOfDeclaration(";", NULL)) {
448 return;
449 } else if (TryConsume("{")) {
450 SkipRestOfBlock();
451 return;
452 } else if (LookingAt("}")) {
453 return;
454 }
455 }
456 input_->Next();
457 }
458}
459
460void Parser::SkipRestOfBlock() {
461 while (true) {
462 if (AtEnd()) {
463 return;
464 } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) {
465 if (TryConsumeEndOfDeclaration("}", NULL)) {
466 return;
467 } else if (TryConsume("{")) {
468 SkipRestOfBlock();
469 }
470 }
471 input_->Next();
472 }
473}
474
475// ===================================================================
476
477bool Parser::ValidateEnum(const EnumDescriptorProto* proto) {
478 bool has_allow_alias = false;
479 bool allow_alias = false;
480
481 for (int i = 0; i < proto->options().uninterpreted_option_size(); i++) {
482 const UninterpretedOption option = proto->options().uninterpreted_option(i);
483 if (option.name_size() > 1) {
484 continue;
485 }
486 if (!option.name(0).is_extension() &&
487 option.name(0).name_part() == "allow_alias") {
488 has_allow_alias = true;
489 if (option.identifier_value() == "true") {
490 allow_alias = true;
491 }
492 break;
493 }
494 }
495
496 if (has_allow_alias && !allow_alias) {
497 string error =
498 "\"" + proto->name() +
499 "\" declares 'option allow_alias = false;' which has no effect. "
500 "Please remove the declaration.";
501 // This needlessly clutters declarations with nops.
502 AddError(error);
503 return false;
504 }
505
Austin Schuh40c16522018-10-28 20:27:54 -0700506 std::set<int> used_values;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500507 bool has_duplicates = false;
508 for (int i = 0; i < proto->value_size(); ++i) {
509 const EnumValueDescriptorProto enum_value = proto->value(i);
510 if (used_values.find(enum_value.number()) != used_values.end()) {
511 has_duplicates = true;
512 break;
513 } else {
514 used_values.insert(enum_value.number());
515 }
516 }
517 if (allow_alias && !has_duplicates) {
518 string error =
519 "\"" + proto->name() +
520 "\" declares support for enum aliases but no enum values share field "
521 "numbers. Please remove the unnecessary 'option allow_alias = true;' "
522 "declaration.";
523 // Generate an error if an enum declares support for duplicate enum values
524 // and does not use it protect future authors.
525 AddError(error);
526 return false;
527 }
528
529 return true;
530}
531
532bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
533 input_ = input;
534 had_errors_ = false;
535 syntax_identifier_.clear();
536
537 // Note that |file| could be NULL at this point if
538 // stop_after_syntax_identifier_ is true. So, we conservatively allocate
539 // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto
540 // later on.
541 SourceCodeInfo source_code_info;
542 source_code_info_ = &source_code_info;
543
Brian Silverman9c614bc2016-02-15 20:20:02 -0500544 if (LookingAtType(io::Tokenizer::TYPE_START)) {
545 // Advance to first token.
546 input_->NextWithComments(NULL, &upcoming_detached_comments_,
547 &upcoming_doc_comments_);
548 }
549
550 {
551 LocationRecorder root_location(this);
552
553 if (require_syntax_identifier_ || LookingAt("syntax")) {
554 if (!ParseSyntaxIdentifier(root_location)) {
555 // Don't attempt to parse the file if we didn't recognize the syntax
556 // identifier.
557 return false;
558 }
559 // Store the syntax into the file.
560 if (file != NULL) file->set_syntax(syntax_identifier_);
561 } else if (!stop_after_syntax_identifier_) {
562 GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: "
563 << file->name() << ". Please use 'syntax = \"proto2\";' "
564 << "or 'syntax = \"proto3\";' to specify a syntax "
565 << "version. (Defaulted to proto2 syntax.)";
566 syntax_identifier_ = "proto2";
567 }
568
569 if (stop_after_syntax_identifier_) return !had_errors_;
570
571 // Repeatedly parse statements until we reach the end of the file.
572 while (!AtEnd()) {
573 if (!ParseTopLevelStatement(file, root_location)) {
574 // This statement failed to parse. Skip it, but keep looping to parse
575 // other statements.
576 SkipStatement();
577
578 if (LookingAt("}")) {
579 AddError("Unmatched \"}\".");
580 input_->NextWithComments(NULL, &upcoming_detached_comments_,
581 &upcoming_doc_comments_);
582 }
583 }
584 }
585 }
586
587 input_ = NULL;
588 source_code_info_ = NULL;
Austin Schuh40c16522018-10-28 20:27:54 -0700589 assert(file != NULL);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500590 source_code_info.Swap(file->mutable_source_code_info());
591 return !had_errors_;
592}
593
594bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
595 LocationRecorder syntax_location(parent,
596 FileDescriptorProto::kSyntaxFieldNumber);
597 DO(Consume(
598 "syntax",
599 "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
600 DO(Consume("="));
601 io::Tokenizer::Token syntax_token = input_->current();
602 string syntax;
603 DO(ConsumeString(&syntax, "Expected syntax identifier."));
604 DO(ConsumeEndOfDeclaration(";", &syntax_location));
605
606 syntax_identifier_ = syntax;
607
608 if (syntax != "proto2" && syntax != "proto3" &&
609 !stop_after_syntax_identifier_) {
610 AddError(syntax_token.line, syntax_token.column,
611 "Unrecognized syntax identifier \"" + syntax + "\". This parser "
612 "only recognizes \"proto2\" and \"proto3\".");
613 return false;
614 }
615
616 return true;
617}
618
619bool Parser::ParseTopLevelStatement(FileDescriptorProto* file,
620 const LocationRecorder& root_location) {
621 if (TryConsumeEndOfDeclaration(";", NULL)) {
622 // empty statement; ignore
623 return true;
624 } else if (LookingAt("message")) {
625 LocationRecorder location(root_location,
626 FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size());
627 return ParseMessageDefinition(file->add_message_type(), location, file);
628 } else if (LookingAt("enum")) {
629 LocationRecorder location(root_location,
630 FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size());
631 return ParseEnumDefinition(file->add_enum_type(), location, file);
632 } else if (LookingAt("service")) {
633 LocationRecorder location(root_location,
634 FileDescriptorProto::kServiceFieldNumber, file->service_size());
635 return ParseServiceDefinition(file->add_service(), location, file);
636 } else if (LookingAt("extend")) {
637 LocationRecorder location(root_location,
638 FileDescriptorProto::kExtensionFieldNumber);
639 return ParseExtend(file->mutable_extension(),
640 file->mutable_message_type(),
641 root_location,
642 FileDescriptorProto::kMessageTypeFieldNumber,
643 location, file);
644 } else if (LookingAt("import")) {
645 return ParseImport(file->mutable_dependency(),
646 file->mutable_public_dependency(),
647 file->mutable_weak_dependency(),
648 root_location, file);
649 } else if (LookingAt("package")) {
650 return ParsePackage(file, root_location, file);
651 } else if (LookingAt("option")) {
652 LocationRecorder location(root_location,
653 FileDescriptorProto::kOptionsFieldNumber);
654 return ParseOption(file->mutable_options(), location, file,
655 OPTION_STATEMENT);
656 } else {
657 AddError("Expected top-level statement (e.g. \"message\").");
658 return false;
659 }
660}
661
662// -------------------------------------------------------------------
663// Messages
664
665bool Parser::ParseMessageDefinition(
666 DescriptorProto* message,
667 const LocationRecorder& message_location,
668 const FileDescriptorProto* containing_file) {
669 DO(Consume("message"));
670 {
671 LocationRecorder location(message_location,
672 DescriptorProto::kNameFieldNumber);
673 location.RecordLegacyLocation(
674 message, DescriptorPool::ErrorCollector::NAME);
675 DO(ConsumeIdentifier(message->mutable_name(), "Expected message name."));
676 }
677 DO(ParseMessageBlock(message, message_location, containing_file));
678 return true;
679}
680
681namespace {
682
Austin Schuh40c16522018-10-28 20:27:54 -0700683const int kMaxRangeSentinel = -1;
Brian Silverman9c614bc2016-02-15 20:20:02 -0500684
685bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
686 const MessageOptions& options = message.options();
687 for (int i = 0; i < options.uninterpreted_option_size(); ++i) {
688 const UninterpretedOption& uninterpreted = options.uninterpreted_option(i);
689 if (uninterpreted.name_size() == 1 &&
690 uninterpreted.name(0).name_part() == "message_set_wire_format" &&
691 uninterpreted.identifier_value() == "true") {
692 return true;
693 }
694 }
695 return false;
696}
697
698// Modifies any extension ranges that specified 'max' as the end of the
699// extension range, and sets them to the type-specific maximum. The actual max
700// tag number can only be determined after all options have been parsed.
701void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
702 const bool is_message_set = IsMessageSetWireFormatMessage(*message);
703 const int max_extension_number = is_message_set ?
704 kint32max :
705 FieldDescriptor::kMaxNumber + 1;
706 for (int i = 0; i < message->extension_range_size(); ++i) {
Austin Schuh40c16522018-10-28 20:27:54 -0700707 if (message->extension_range(i).end() == kMaxRangeSentinel) {
Brian Silverman9c614bc2016-02-15 20:20:02 -0500708 message->mutable_extension_range(i)->set_end(max_extension_number);
709 }
710 }
711}
712
Austin Schuh40c16522018-10-28 20:27:54 -0700713// Modifies any reserved ranges that specified 'max' as the end of the
714// reserved range, and sets them to the type-specific maximum. The actual max
715// tag number can only be determined after all options have been parsed.
716void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
717 const bool is_message_set = IsMessageSetWireFormatMessage(*message);
718 const int max_field_number = is_message_set ?
719 kint32max :
720 FieldDescriptor::kMaxNumber + 1;
721 for (int i = 0; i < message->reserved_range_size(); ++i) {
722 if (message->reserved_range(i).end() == kMaxRangeSentinel) {
723 message->mutable_reserved_range(i)->set_end(max_field_number);
724 }
725 }
726}
727
Brian Silverman9c614bc2016-02-15 20:20:02 -0500728} // namespace
729
730bool Parser::ParseMessageBlock(DescriptorProto* message,
731 const LocationRecorder& message_location,
732 const FileDescriptorProto* containing_file) {
733 DO(ConsumeEndOfDeclaration("{", &message_location));
734
735 while (!TryConsumeEndOfDeclaration("}", NULL)) {
736 if (AtEnd()) {
737 AddError("Reached end of input in message definition (missing '}').");
738 return false;
739 }
740
741 if (!ParseMessageStatement(message, message_location, containing_file)) {
742 // This statement failed to parse. Skip it, but keep looping to parse
743 // other statements.
744 SkipStatement();
745 }
746 }
747
748 if (message->extension_range_size() > 0) {
749 AdjustExtensionRangesWithMaxEndNumber(message);
750 }
Austin Schuh40c16522018-10-28 20:27:54 -0700751 if (message->reserved_range_size() > 0) {
752 AdjustReservedRangesWithMaxEndNumber(message);
753 }
Brian Silverman9c614bc2016-02-15 20:20:02 -0500754 return true;
755}
756
757bool Parser::ParseMessageStatement(DescriptorProto* message,
758 const LocationRecorder& message_location,
759 const FileDescriptorProto* containing_file) {
760 if (TryConsumeEndOfDeclaration(";", NULL)) {
761 // empty statement; ignore
762 return true;
763 } else if (LookingAt("message")) {
764 LocationRecorder location(message_location,
765 DescriptorProto::kNestedTypeFieldNumber,
766 message->nested_type_size());
767 return ParseMessageDefinition(message->add_nested_type(), location,
768 containing_file);
769 } else if (LookingAt("enum")) {
770 LocationRecorder location(message_location,
771 DescriptorProto::kEnumTypeFieldNumber,
772 message->enum_type_size());
773 return ParseEnumDefinition(message->add_enum_type(), location,
774 containing_file);
775 } else if (LookingAt("extensions")) {
776 LocationRecorder location(message_location,
777 DescriptorProto::kExtensionRangeFieldNumber);
778 return ParseExtensions(message, location, containing_file);
779 } else if (LookingAt("reserved")) {
780 return ParseReserved(message, message_location);
781 } else if (LookingAt("extend")) {
782 LocationRecorder location(message_location,
783 DescriptorProto::kExtensionFieldNumber);
784 return ParseExtend(message->mutable_extension(),
785 message->mutable_nested_type(),
786 message_location,
787 DescriptorProto::kNestedTypeFieldNumber,
788 location, containing_file);
789 } else if (LookingAt("option")) {
790 LocationRecorder location(message_location,
791 DescriptorProto::kOptionsFieldNumber);
792 return ParseOption(message->mutable_options(), location,
793 containing_file, OPTION_STATEMENT);
794 } else if (LookingAt("oneof")) {
795 int oneof_index = message->oneof_decl_size();
796 LocationRecorder oneof_location(message_location,
797 DescriptorProto::kOneofDeclFieldNumber,
798 oneof_index);
799
800 return ParseOneof(message->add_oneof_decl(), message,
801 oneof_index, oneof_location, message_location,
802 containing_file);
803 } else {
804 LocationRecorder location(message_location,
805 DescriptorProto::kFieldFieldNumber,
806 message->field_size());
807 return ParseMessageField(message->add_field(),
808 message->mutable_nested_type(),
809 message_location,
810 DescriptorProto::kNestedTypeFieldNumber,
811 location,
812 containing_file);
813 }
814}
815
816bool Parser::ParseMessageField(FieldDescriptorProto* field,
817 RepeatedPtrField<DescriptorProto>* messages,
818 const LocationRecorder& parent_location,
819 int location_field_number_for_nested_type,
820 const LocationRecorder& field_location,
821 const FileDescriptorProto* containing_file) {
822 {
823 LocationRecorder location(field_location,
824 FieldDescriptorProto::kLabelFieldNumber);
825 FieldDescriptorProto::Label label;
826 if (ParseLabel(&label, containing_file)) {
827 field->set_label(label);
828 if (label == FieldDescriptorProto::LABEL_OPTIONAL &&
829 syntax_identifier_ == "proto3") {
830 AddError(
831 "Explicit 'optional' labels are disallowed in the Proto3 syntax. "
832 "To define 'optional' fields in Proto3, simply remove the "
833 "'optional' label, as fields are 'optional' by default.");
834 }
835 }
836 }
837
838 return ParseMessageFieldNoLabel(field, messages, parent_location,
839 location_field_number_for_nested_type,
840 field_location,
841 containing_file);
842}
843
844bool Parser::ParseMessageFieldNoLabel(
845 FieldDescriptorProto* field,
846 RepeatedPtrField<DescriptorProto>* messages,
847 const LocationRecorder& parent_location,
848 int location_field_number_for_nested_type,
849 const LocationRecorder& field_location,
850 const FileDescriptorProto* containing_file) {
851 MapField map_field;
852 // Parse type.
853 {
854 LocationRecorder location(field_location); // add path later
855 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
856
857 bool type_parsed = false;
858 FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
859 string type_name;
860
861 // Special case map field. We only treat the field as a map field if the
862 // field type name starts with the word "map" with a following "<".
863 if (TryConsume("map")) {
864 if (LookingAt("<")) {
865 map_field.is_map_field = true;
866 } else {
867 // False positive
868 type_parsed = true;
869 type_name = "map";
870 }
871 }
872 if (map_field.is_map_field) {
873 if (field->has_oneof_index()) {
874 AddError("Map fields are not allowed in oneofs.");
875 return false;
876 }
877 if (field->has_label()) {
878 AddError(
879 "Field labels (required/optional/repeated) are not allowed on "
880 "map fields.");
881 return false;
882 }
883 if (field->has_extendee()) {
884 AddError("Map fields are not allowed to be extensions.");
885 return false;
886 }
887 field->set_label(FieldDescriptorProto::LABEL_REPEATED);
888 DO(Consume("<"));
889 DO(ParseType(&map_field.key_type, &map_field.key_type_name));
890 DO(Consume(","));
891 DO(ParseType(&map_field.value_type, &map_field.value_type_name));
892 DO(Consume(">"));
893 // Defer setting of the type name of the map field until the
894 // field name is parsed. Add the source location though.
895 location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
896 } else {
897 // Handle the case where no explicit label is given for a non-map field.
898 if (!field->has_label() && DefaultToOptionalFields()) {
899 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
900 }
901 if (!field->has_label()) {
902 AddError("Expected \"required\", \"optional\", or \"repeated\".");
903 // We can actually reasonably recover here by just assuming the user
904 // forgot the label altogether.
905 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
906 }
907
908 // Handle the case where the actual type is a message or enum named "map",
909 // which we already consumed in the code above.
910 if (!type_parsed) {
911 DO(ParseType(&type, &type_name));
912 }
913 if (type_name.empty()) {
914 location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
915 field->set_type(type);
916 } else {
917 location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
918 field->set_type_name(type_name);
919 }
920 }
921 }
922
923 // Parse name and '='.
924 io::Tokenizer::Token name_token = input_->current();
925 {
926 LocationRecorder location(field_location,
927 FieldDescriptorProto::kNameFieldNumber);
928 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME);
929 DO(ConsumeIdentifier(field->mutable_name(), "Expected field name."));
930 }
931 DO(Consume("=", "Missing field number."));
932
933 // Parse field number.
934 {
935 LocationRecorder location(field_location,
936 FieldDescriptorProto::kNumberFieldNumber);
937 location.RecordLegacyLocation(
938 field, DescriptorPool::ErrorCollector::NUMBER);
939 int number;
940 DO(ConsumeInteger(&number, "Expected field number."));
941 field->set_number(number);
942 }
943
944 // Parse options.
945 DO(ParseFieldOptions(field, field_location, containing_file));
946
947 // Deal with groups.
948 if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) {
949 // Awkward: Since a group declares both a message type and a field, we
950 // have to create overlapping locations.
951 LocationRecorder group_location(parent_location);
952 group_location.StartAt(field_location);
953 group_location.AddPath(location_field_number_for_nested_type);
954 group_location.AddPath(messages->size());
955
956 DescriptorProto* group = messages->Add();
957 group->set_name(field->name());
958
959 // Record name location to match the field name's location.
960 {
961 LocationRecorder location(group_location,
962 DescriptorProto::kNameFieldNumber);
963 location.StartAt(name_token);
964 location.EndAt(name_token);
965 location.RecordLegacyLocation(
966 group, DescriptorPool::ErrorCollector::NAME);
967 }
968
969 // The field's type_name also comes from the name. Confusing!
970 {
971 LocationRecorder location(field_location,
972 FieldDescriptorProto::kTypeNameFieldNumber);
973 location.StartAt(name_token);
974 location.EndAt(name_token);
975 }
976
977 // As a hack for backwards-compatibility, we force the group name to start
978 // with a capital letter and lower-case the field name. New code should
979 // not use groups; it should use nested messages.
980 if (group->name()[0] < 'A' || 'Z' < group->name()[0]) {
981 AddError(name_token.line, name_token.column,
982 "Group names must start with a capital letter.");
983 }
984 LowerString(field->mutable_name());
985
986 field->set_type_name(group->name());
987 if (LookingAt("{")) {
988 DO(ParseMessageBlock(group, group_location, containing_file));
989 } else {
990 AddError("Missing group body.");
991 return false;
992 }
993 } else {
994 DO(ConsumeEndOfDeclaration(";", &field_location));
995 }
996
997 // Create a map entry type if this is a map field.
998 if (map_field.is_map_field) {
999 GenerateMapEntry(map_field, field, messages);
1000 }
1001
1002 return true;
1003}
1004
1005void Parser::GenerateMapEntry(const MapField& map_field,
1006 FieldDescriptorProto* field,
1007 RepeatedPtrField<DescriptorProto>* messages) {
1008 DescriptorProto* entry = messages->Add();
1009 string entry_name = MapEntryName(field->name());
1010 field->set_type_name(entry_name);
1011 entry->set_name(entry_name);
1012 entry->mutable_options()->set_map_entry(true);
1013 FieldDescriptorProto* key_field = entry->add_field();
1014 key_field->set_name("key");
1015 key_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
1016 key_field->set_number(1);
1017 if (map_field.key_type_name.empty()) {
1018 key_field->set_type(map_field.key_type);
1019 } else {
1020 key_field->set_type_name(map_field.key_type_name);
1021 }
1022 FieldDescriptorProto* value_field = entry->add_field();
1023 value_field->set_name("value");
1024 value_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
1025 value_field->set_number(2);
1026 if (map_field.value_type_name.empty()) {
1027 value_field->set_type(map_field.value_type);
1028 } else {
1029 value_field->set_type_name(map_field.value_type_name);
1030 }
1031 // Propagate the "enforce_utf8" option to key and value fields if they
1032 // are strings. This helps simplify the implementation of code generators
1033 // and also reflection-based parsing code.
1034 //
1035 // The following definition:
1036 // message Foo {
1037 // map<string, string> value = 1 [enforce_utf8 = false];
1038 // }
1039 // will be interpreted as:
1040 // message Foo {
1041 // message ValueEntry {
1042 // option map_entry = true;
1043 // string key = 1 [enforce_utf8 = false];
1044 // string value = 2 [enforce_utf8 = false];
1045 // }
1046 // repeated ValueEntry value = 1 [enforce_utf8 = false];
1047 // }
1048 //
1049 // TODO(xiaofeng): Remove this when the "enforce_utf8" option is removed
1050 // from protocol compiler.
1051 for (int i = 0; i < field->options().uninterpreted_option_size(); ++i) {
1052 const UninterpretedOption& option =
1053 field->options().uninterpreted_option(i);
1054 if (option.name_size() == 1 &&
1055 option.name(0).name_part() == "enforce_utf8" &&
1056 !option.name(0).is_extension()) {
1057 if (key_field->type() == FieldDescriptorProto::TYPE_STRING) {
1058 key_field->mutable_options()->add_uninterpreted_option()
1059 ->CopyFrom(option);
1060 }
1061 if (value_field->type() == FieldDescriptorProto::TYPE_STRING) {
1062 value_field->mutable_options()->add_uninterpreted_option()
1063 ->CopyFrom(option);
1064 }
1065 }
1066 }
1067}
1068
1069bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
1070 const LocationRecorder& field_location,
1071 const FileDescriptorProto* containing_file) {
1072 if (!LookingAt("[")) return true;
1073
1074 LocationRecorder location(field_location,
1075 FieldDescriptorProto::kOptionsFieldNumber);
1076
1077 DO(Consume("["));
1078
1079 // Parse field options.
1080 do {
1081 if (LookingAt("default")) {
1082 // We intentionally pass field_location rather than location here, since
1083 // the default value is not actually an option.
1084 DO(ParseDefaultAssignment(field, field_location, containing_file));
1085 } else if (LookingAt("json_name")) {
1086 // Like default value, this "json_name" is not an actual option.
1087 DO(ParseJsonName(field, field_location, containing_file));
1088 } else {
1089 DO(ParseOption(field->mutable_options(), location,
1090 containing_file, OPTION_ASSIGNMENT));
1091 }
1092 } while (TryConsume(","));
1093
1094 DO(Consume("]"));
1095 return true;
1096}
1097
1098bool Parser::ParseDefaultAssignment(
1099 FieldDescriptorProto* field,
1100 const LocationRecorder& field_location,
1101 const FileDescriptorProto* containing_file) {
1102 if (field->has_default_value()) {
1103 AddError("Already set option \"default\".");
1104 field->clear_default_value();
1105 }
1106
1107 DO(Consume("default"));
1108 DO(Consume("="));
1109
1110 LocationRecorder location(field_location,
1111 FieldDescriptorProto::kDefaultValueFieldNumber);
1112 location.RecordLegacyLocation(
1113 field, DescriptorPool::ErrorCollector::DEFAULT_VALUE);
1114 string* default_value = field->mutable_default_value();
1115
1116 if (!field->has_type()) {
1117 // The field has a type name, but we don't know if it is a message or an
1118 // enum yet. (If it were a primitive type, |field| would have a type set
1119 // already.) In this case, simply take the current string as the default
1120 // value; we will catch the error later if it is not a valid enum value.
1121 // (N.B. that we do not check whether the current token is an identifier:
1122 // doing so throws strange errors when the user mistypes a primitive
1123 // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default
1124 // = 42]". In such a case the fundamental error is really that "int" is not
1125 // a type, not that "42" is not an identifier. See b/12533582.)
1126 *default_value = input_->current().text;
1127 input_->Next();
1128 return true;
1129 }
1130
1131 switch (field->type()) {
1132 case FieldDescriptorProto::TYPE_INT32:
1133 case FieldDescriptorProto::TYPE_INT64:
1134 case FieldDescriptorProto::TYPE_SINT32:
1135 case FieldDescriptorProto::TYPE_SINT64:
1136 case FieldDescriptorProto::TYPE_SFIXED32:
1137 case FieldDescriptorProto::TYPE_SFIXED64: {
1138 uint64 max_value = kint64max;
1139 if (field->type() == FieldDescriptorProto::TYPE_INT32 ||
1140 field->type() == FieldDescriptorProto::TYPE_SINT32 ||
1141 field->type() == FieldDescriptorProto::TYPE_SFIXED32) {
1142 max_value = kint32max;
1143 }
1144
1145 // These types can be negative.
1146 if (TryConsume("-")) {
1147 default_value->append("-");
1148 // Two's complement always has one more negative value than positive.
1149 ++max_value;
1150 }
1151 // Parse the integer to verify that it is not out-of-range.
1152 uint64 value;
1153 DO(ConsumeInteger64(max_value, &value,
1154 "Expected integer for field default value."));
1155 // And stringify it again.
1156 default_value->append(SimpleItoa(value));
1157 break;
1158 }
1159
1160 case FieldDescriptorProto::TYPE_UINT32:
1161 case FieldDescriptorProto::TYPE_UINT64:
1162 case FieldDescriptorProto::TYPE_FIXED32:
1163 case FieldDescriptorProto::TYPE_FIXED64: {
1164 uint64 max_value = kuint64max;
1165 if (field->type() == FieldDescriptorProto::TYPE_UINT32 ||
1166 field->type() == FieldDescriptorProto::TYPE_FIXED32) {
1167 max_value = kuint32max;
1168 }
1169
1170 // Numeric, not negative.
1171 if (TryConsume("-")) {
1172 AddError("Unsigned field can't have negative default value.");
1173 }
1174 // Parse the integer to verify that it is not out-of-range.
1175 uint64 value;
1176 DO(ConsumeInteger64(max_value, &value,
1177 "Expected integer for field default value."));
1178 // And stringify it again.
1179 default_value->append(SimpleItoa(value));
1180 break;
1181 }
1182
1183 case FieldDescriptorProto::TYPE_FLOAT:
1184 case FieldDescriptorProto::TYPE_DOUBLE:
1185 // These types can be negative.
1186 if (TryConsume("-")) {
1187 default_value->append("-");
1188 }
1189 // Parse the integer because we have to convert hex integers to decimal
1190 // floats.
1191 double value;
1192 DO(ConsumeNumber(&value, "Expected number."));
1193 // And stringify it again.
1194 default_value->append(SimpleDtoa(value));
1195 break;
1196
1197 case FieldDescriptorProto::TYPE_BOOL:
1198 if (TryConsume("true")) {
1199 default_value->assign("true");
1200 } else if (TryConsume("false")) {
1201 default_value->assign("false");
1202 } else {
1203 AddError("Expected \"true\" or \"false\".");
1204 return false;
1205 }
1206 break;
1207
1208 case FieldDescriptorProto::TYPE_STRING:
1209 // Note: When file opton java_string_check_utf8 is true, if a
1210 // non-string representation (eg byte[]) is later supported, it must
1211 // be checked for UTF-8-ness.
1212 DO(ConsumeString(default_value, "Expected string for field default "
1213 "value."));
1214 break;
1215
1216 case FieldDescriptorProto::TYPE_BYTES:
1217 DO(ConsumeString(default_value, "Expected string."));
1218 *default_value = CEscape(*default_value);
1219 break;
1220
1221 case FieldDescriptorProto::TYPE_ENUM:
1222 DO(ConsumeIdentifier(default_value, "Expected enum identifier for field "
1223 "default value."));
1224 break;
1225
1226 case FieldDescriptorProto::TYPE_MESSAGE:
1227 case FieldDescriptorProto::TYPE_GROUP:
1228 AddError("Messages can't have default values.");
1229 return false;
1230 }
1231
1232 return true;
1233}
1234
1235bool Parser::ParseJsonName(
1236 FieldDescriptorProto* field,
1237 const LocationRecorder& field_location,
1238 const FileDescriptorProto* containing_file) {
1239 if (field->has_json_name()) {
1240 AddError("Already set option \"json_name\".");
1241 field->clear_json_name();
1242 }
1243
1244 DO(Consume("json_name"));
1245 DO(Consume("="));
1246
1247 LocationRecorder location(field_location,
1248 FieldDescriptorProto::kJsonNameFieldNumber);
1249 location.RecordLegacyLocation(
1250 field, DescriptorPool::ErrorCollector::OPTION_VALUE);
1251 DO(ConsumeString(field->mutable_json_name(),
1252 "Expected string for JSON name."));
1253 return true;
1254}
1255
1256
1257bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
1258 const LocationRecorder& part_location,
1259 const FileDescriptorProto* containing_file) {
1260 UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
1261 string identifier; // We parse identifiers into this string.
1262 if (LookingAt("(")) { // This is an extension.
1263 DO(Consume("("));
1264
1265 {
1266 LocationRecorder location(
1267 part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
1268 // An extension name consists of dot-separated identifiers, and may begin
1269 // with a dot.
1270 if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
1271 DO(ConsumeIdentifier(&identifier, "Expected identifier."));
1272 name->mutable_name_part()->append(identifier);
1273 }
1274 while (LookingAt(".")) {
1275 DO(Consume("."));
1276 name->mutable_name_part()->append(".");
1277 DO(ConsumeIdentifier(&identifier, "Expected identifier."));
1278 name->mutable_name_part()->append(identifier);
1279 }
1280 }
1281
1282 DO(Consume(")"));
1283 name->set_is_extension(true);
1284 } else { // This is a regular field.
1285 LocationRecorder location(
1286 part_location, UninterpretedOption::NamePart::kNamePartFieldNumber);
1287 DO(ConsumeIdentifier(&identifier, "Expected identifier."));
1288 name->mutable_name_part()->append(identifier);
1289 name->set_is_extension(false);
1290 }
1291 return true;
1292}
1293
1294bool Parser::ParseUninterpretedBlock(string* value) {
1295 // Note that enclosing braces are not added to *value.
1296 // We do NOT use ConsumeEndOfStatement for this brace because it's delimiting
1297 // an expression, not a block of statements.
1298 DO(Consume("{"));
1299 int brace_depth = 1;
1300 while (!AtEnd()) {
1301 if (LookingAt("{")) {
1302 brace_depth++;
1303 } else if (LookingAt("}")) {
1304 brace_depth--;
1305 if (brace_depth == 0) {
1306 input_->Next();
1307 return true;
1308 }
1309 }
1310 // TODO(sanjay): Interpret line/column numbers to preserve formatting
1311 if (!value->empty()) value->push_back(' ');
1312 value->append(input_->current().text);
1313 input_->Next();
1314 }
1315 AddError("Unexpected end of stream while parsing aggregate value.");
1316 return false;
1317}
1318
1319// We don't interpret the option here. Instead we store it in an
1320// UninterpretedOption, to be interpreted later.
1321bool Parser::ParseOption(Message* options,
1322 const LocationRecorder& options_location,
1323 const FileDescriptorProto* containing_file,
1324 OptionStyle style) {
1325 // Create an entry in the uninterpreted_option field.
1326 const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
1327 FindFieldByName("uninterpreted_option");
1328 GOOGLE_CHECK(uninterpreted_option_field != NULL)
1329 << "No field named \"uninterpreted_option\" in the Options proto.";
1330
1331 const Reflection* reflection = options->GetReflection();
1332
1333 LocationRecorder location(
1334 options_location, uninterpreted_option_field->number(),
1335 reflection->FieldSize(*options, uninterpreted_option_field));
1336
1337 if (style == OPTION_STATEMENT) {
1338 DO(Consume("option"));
1339 }
1340
1341 UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>(
1342 options->GetReflection()->AddMessage(options,
1343 uninterpreted_option_field));
1344
1345 // Parse dot-separated name.
1346 {
1347 LocationRecorder name_location(location,
1348 UninterpretedOption::kNameFieldNumber);
1349 name_location.RecordLegacyLocation(
1350 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME);
1351
1352 {
1353 LocationRecorder part_location(name_location,
1354 uninterpreted_option->name_size());
1355 DO(ParseOptionNamePart(uninterpreted_option, part_location,
1356 containing_file));
1357 }
1358
1359 while (LookingAt(".")) {
1360 DO(Consume("."));
1361 LocationRecorder part_location(name_location,
1362 uninterpreted_option->name_size());
1363 DO(ParseOptionNamePart(uninterpreted_option, part_location,
1364 containing_file));
1365 }
1366 }
1367
1368 DO(Consume("="));
1369
1370 {
1371 LocationRecorder value_location(location);
1372 value_location.RecordLegacyLocation(
1373 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE);
1374
1375 // All values are a single token, except for negative numbers, which consist
1376 // of a single '-' symbol, followed by a positive number.
1377 bool is_negative = TryConsume("-");
1378
1379 switch (input_->current().type) {
1380 case io::Tokenizer::TYPE_START:
1381 GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
1382 return false;
1383
1384 case io::Tokenizer::TYPE_END:
1385 AddError("Unexpected end of stream while parsing option value.");
1386 return false;
1387
1388 case io::Tokenizer::TYPE_IDENTIFIER: {
1389 value_location.AddPath(
1390 UninterpretedOption::kIdentifierValueFieldNumber);
1391 if (is_negative) {
1392 AddError("Invalid '-' symbol before identifier.");
1393 return false;
1394 }
1395 string value;
1396 DO(ConsumeIdentifier(&value, "Expected identifier."));
1397 uninterpreted_option->set_identifier_value(value);
1398 break;
1399 }
1400
1401 case io::Tokenizer::TYPE_INTEGER: {
1402 uint64 value;
1403 uint64 max_value =
1404 is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
1405 DO(ConsumeInteger64(max_value, &value, "Expected integer."));
1406 if (is_negative) {
1407 value_location.AddPath(
1408 UninterpretedOption::kNegativeIntValueFieldNumber);
1409 uninterpreted_option->set_negative_int_value(
Austin Schuh40c16522018-10-28 20:27:54 -07001410 static_cast<int64>(-value));
Brian Silverman9c614bc2016-02-15 20:20:02 -05001411 } else {
1412 value_location.AddPath(
1413 UninterpretedOption::kPositiveIntValueFieldNumber);
1414 uninterpreted_option->set_positive_int_value(value);
1415 }
1416 break;
1417 }
1418
1419 case io::Tokenizer::TYPE_FLOAT: {
1420 value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
1421 double value;
1422 DO(ConsumeNumber(&value, "Expected number."));
1423 uninterpreted_option->set_double_value(is_negative ? -value : value);
1424 break;
1425 }
1426
1427 case io::Tokenizer::TYPE_STRING: {
1428 value_location.AddPath(UninterpretedOption::kStringValueFieldNumber);
1429 if (is_negative) {
1430 AddError("Invalid '-' symbol before string.");
1431 return false;
1432 }
1433 string value;
1434 DO(ConsumeString(&value, "Expected string."));
1435 uninterpreted_option->set_string_value(value);
1436 break;
1437 }
1438
1439 case io::Tokenizer::TYPE_SYMBOL:
1440 if (LookingAt("{")) {
1441 value_location.AddPath(
1442 UninterpretedOption::kAggregateValueFieldNumber);
1443 DO(ParseUninterpretedBlock(
1444 uninterpreted_option->mutable_aggregate_value()));
1445 } else {
1446 AddError("Expected option value.");
1447 return false;
1448 }
1449 break;
1450 }
1451 }
1452
1453 if (style == OPTION_STATEMENT) {
1454 DO(ConsumeEndOfDeclaration(";", &location));
1455 }
1456
1457 return true;
1458}
1459
1460bool Parser::ParseExtensions(DescriptorProto* message,
1461 const LocationRecorder& extensions_location,
1462 const FileDescriptorProto* containing_file) {
1463 // Parse the declaration.
1464 DO(Consume("extensions"));
1465
Austin Schuh40c16522018-10-28 20:27:54 -07001466 int old_range_size = message->extension_range_size();
1467
Brian Silverman9c614bc2016-02-15 20:20:02 -05001468 do {
1469 // Note that kExtensionRangeFieldNumber was already pushed by the parent.
1470 LocationRecorder location(extensions_location,
1471 message->extension_range_size());
1472
1473 DescriptorProto::ExtensionRange* range = message->add_extension_range();
1474 location.RecordLegacyLocation(
1475 range, DescriptorPool::ErrorCollector::NUMBER);
1476
1477 int start, end;
1478 io::Tokenizer::Token start_token;
1479
1480 {
1481 LocationRecorder start_location(
1482 location, DescriptorProto::ExtensionRange::kStartFieldNumber);
1483 start_token = input_->current();
1484 DO(ConsumeInteger(&start, "Expected field number range."));
1485 }
1486
1487 if (TryConsume("to")) {
1488 LocationRecorder end_location(
1489 location, DescriptorProto::ExtensionRange::kEndFieldNumber);
1490 if (TryConsume("max")) {
1491 // Set to the sentinel value - 1 since we increment the value below.
1492 // The actual value of the end of the range should be set with
1493 // AdjustExtensionRangesWithMaxEndNumber.
Austin Schuh40c16522018-10-28 20:27:54 -07001494 end = kMaxRangeSentinel - 1;
Brian Silverman9c614bc2016-02-15 20:20:02 -05001495 } else {
1496 DO(ConsumeInteger(&end, "Expected integer."));
1497 }
1498 } else {
1499 LocationRecorder end_location(
1500 location, DescriptorProto::ExtensionRange::kEndFieldNumber);
1501 end_location.StartAt(start_token);
1502 end_location.EndAt(start_token);
1503 end = start;
1504 }
1505
1506 // Users like to specify inclusive ranges, but in code we like the end
1507 // number to be exclusive.
1508 ++end;
1509
1510 range->set_start(start);
1511 range->set_end(end);
1512 } while (TryConsume(","));
1513
Austin Schuh40c16522018-10-28 20:27:54 -07001514
1515 if (LookingAt("[")) {
1516 int range_number_index = extensions_location.CurrentPathSize();
1517 SourceCodeInfo info;
1518
1519 // Parse extension range options in the first range.
1520 ExtensionRangeOptions* options =
1521 message->mutable_extension_range(old_range_size)->mutable_options();
1522
1523 {
1524 LocationRecorder index_location(
1525 extensions_location, 0 /* we fill this in w/ actual index below */,
1526 &info);
1527 LocationRecorder location(
1528 index_location,
1529 DescriptorProto::ExtensionRange::kOptionsFieldNumber);
1530 DO(Consume("["));
1531
1532 do {
1533 DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT));
1534 } while (TryConsume(","));
1535
1536 DO(Consume("]"));
1537 }
1538
1539 // Then copy the extension range options to all of the other ranges we've
1540 // parsed.
1541 for (int i = old_range_size + 1; i < message->extension_range_size(); i++) {
1542 message->mutable_extension_range(i)->mutable_options()
1543 ->CopyFrom(*options);
1544 }
1545 // and copy source locations to the other ranges, too
1546 for (int i = old_range_size; i < message->extension_range_size(); i++) {
1547 for (int j = 0; j < info.location_size(); j++) {
1548 if (info.location(j).path_size() == range_number_index + 1) {
1549 // this location's path is up to the extension range index, but doesn't
1550 // include options; so it's redundant with location above
1551 continue;
1552 }
1553 SourceCodeInfo_Location* dest = source_code_info_->add_location();
1554 dest->CopyFrom(info.location(j));
1555 dest->set_path(range_number_index, i);
1556 }
1557 }
1558 }
1559
Brian Silverman9c614bc2016-02-15 20:20:02 -05001560 DO(ConsumeEndOfDeclaration(";", &extensions_location));
1561 return true;
1562}
1563
Austin Schuh40c16522018-10-28 20:27:54 -07001564// This is similar to extension range parsing, except that it accepts field
1565// name literals.
Brian Silverman9c614bc2016-02-15 20:20:02 -05001566bool Parser::ParseReserved(DescriptorProto* message,
1567 const LocationRecorder& message_location) {
1568 // Parse the declaration.
1569 DO(Consume("reserved"));
1570 if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
1571 LocationRecorder location(message_location,
1572 DescriptorProto::kReservedNameFieldNumber);
1573 return ParseReservedNames(message, location);
1574 } else {
1575 LocationRecorder location(message_location,
1576 DescriptorProto::kReservedRangeFieldNumber);
1577 return ParseReservedNumbers(message, location);
1578 }
1579}
1580
Brian Silverman9c614bc2016-02-15 20:20:02 -05001581bool Parser::ParseReservedNames(DescriptorProto* message,
1582 const LocationRecorder& parent_location) {
1583 do {
1584 LocationRecorder location(parent_location, message->reserved_name_size());
1585 DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
1586 } while (TryConsume(","));
1587 DO(ConsumeEndOfDeclaration(";", &parent_location));
1588 return true;
1589}
1590
1591bool Parser::ParseReservedNumbers(DescriptorProto* message,
1592 const LocationRecorder& parent_location) {
1593 bool first = true;
1594 do {
1595 LocationRecorder location(parent_location, message->reserved_range_size());
1596
1597 DescriptorProto::ReservedRange* range = message->add_reserved_range();
1598 int start, end;
1599 io::Tokenizer::Token start_token;
1600 {
1601 LocationRecorder start_location(
1602 location, DescriptorProto::ReservedRange::kStartFieldNumber);
1603 start_token = input_->current();
1604 DO(ConsumeInteger(&start, (first ?
1605 "Expected field name or number range." :
1606 "Expected field number range.")));
1607 }
1608
1609 if (TryConsume("to")) {
1610 LocationRecorder end_location(
1611 location, DescriptorProto::ReservedRange::kEndFieldNumber);
Austin Schuh40c16522018-10-28 20:27:54 -07001612 if (TryConsume("max")) {
1613 // Set to the sentinel value - 1 since we increment the value below.
1614 // The actual value of the end of the range should be set with
1615 // AdjustExtensionRangesWithMaxEndNumber.
1616 end = kMaxRangeSentinel - 1;
1617 } else {
1618 DO(ConsumeInteger(&end, "Expected integer."));
1619 }
Brian Silverman9c614bc2016-02-15 20:20:02 -05001620 } else {
1621 LocationRecorder end_location(
1622 location, DescriptorProto::ReservedRange::kEndFieldNumber);
1623 end_location.StartAt(start_token);
1624 end_location.EndAt(start_token);
1625 end = start;
1626 }
1627
1628 // Users like to specify inclusive ranges, but in code we like the end
1629 // number to be exclusive.
1630 ++end;
1631
1632 range->set_start(start);
1633 range->set_end(end);
1634 first = false;
1635 } while (TryConsume(","));
1636
1637 DO(ConsumeEndOfDeclaration(";", &parent_location));
1638 return true;
1639}
1640
Austin Schuh40c16522018-10-28 20:27:54 -07001641bool Parser::ParseReserved(EnumDescriptorProto* message,
1642 const LocationRecorder& message_location) {
1643 // Parse the declaration.
1644 DO(Consume("reserved"));
1645 if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
1646 LocationRecorder location(message_location,
1647 DescriptorProto::kReservedNameFieldNumber);
1648 return ParseReservedNames(message, location);
1649 } else {
1650 LocationRecorder location(message_location,
1651 DescriptorProto::kReservedRangeFieldNumber);
1652 return ParseReservedNumbers(message, location);
1653 }
1654}
1655
1656bool Parser::ParseReservedNames(EnumDescriptorProto* message,
1657 const LocationRecorder& parent_location) {
1658 do {
1659 LocationRecorder location(parent_location, message->reserved_name_size());
1660 DO(ConsumeString(message->add_reserved_name(), "Expected enum value."));
1661 } while (TryConsume(","));
1662 DO(ConsumeEndOfDeclaration(";", &parent_location));
1663 return true;
1664}
1665
1666bool Parser::ParseReservedNumbers(EnumDescriptorProto* message,
1667 const LocationRecorder& parent_location) {
1668 bool first = true;
1669 do {
1670 LocationRecorder location(parent_location, message->reserved_range_size());
1671
1672 EnumDescriptorProto::EnumReservedRange* range =
1673 message->add_reserved_range();
1674 int start, end;
1675 io::Tokenizer::Token start_token;
1676 {
1677 LocationRecorder start_location(
1678 location, EnumDescriptorProto::EnumReservedRange::kStartFieldNumber);
1679 start_token = input_->current();
1680 DO(ConsumeSignedInteger(&start, (first ?
1681 "Expected enum value or number range." :
1682 "Expected enum number range.")));
1683 }
1684
1685 if (TryConsume("to")) {
1686 LocationRecorder end_location(
1687 location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
1688 if (TryConsume("max")) {
1689 // This is in the enum descriptor path, which doesn't have the message
1690 // set duality to fix up, so it doesn't integrate with the sentinel.
1691 end = INT_MAX;
1692 } else {
1693 DO(ConsumeSignedInteger(&end, "Expected integer."));
1694 }
1695 } else {
1696 LocationRecorder end_location(
1697 location, EnumDescriptorProto::EnumReservedRange::kEndFieldNumber);
1698 end_location.StartAt(start_token);
1699 end_location.EndAt(start_token);
1700 end = start;
1701 }
1702
1703 range->set_start(start);
1704 range->set_end(end);
1705 first = false;
1706 } while (TryConsume(","));
1707
1708 DO(ConsumeEndOfDeclaration(";", &parent_location));
1709 return true;
1710}
1711
Brian Silverman9c614bc2016-02-15 20:20:02 -05001712bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
1713 RepeatedPtrField<DescriptorProto>* messages,
1714 const LocationRecorder& parent_location,
1715 int location_field_number_for_nested_type,
1716 const LocationRecorder& extend_location,
1717 const FileDescriptorProto* containing_file) {
1718 DO(Consume("extend"));
1719
1720 // Parse the extendee type.
1721 io::Tokenizer::Token extendee_start = input_->current();
1722 string extendee;
1723 DO(ParseUserDefinedType(&extendee));
1724 io::Tokenizer::Token extendee_end = input_->previous();
1725
1726 // Parse the block.
1727 DO(ConsumeEndOfDeclaration("{", &extend_location));
1728
1729 bool is_first = true;
1730
1731 do {
1732 if (AtEnd()) {
1733 AddError("Reached end of input in extend definition (missing '}').");
1734 return false;
1735 }
1736
1737 // Note that kExtensionFieldNumber was already pushed by the parent.
1738 LocationRecorder location(extend_location, extensions->size());
1739
1740 FieldDescriptorProto* field = extensions->Add();
1741
1742 {
1743 LocationRecorder extendee_location(
1744 location, FieldDescriptorProto::kExtendeeFieldNumber);
1745 extendee_location.StartAt(extendee_start);
1746 extendee_location.EndAt(extendee_end);
1747
1748 if (is_first) {
1749 extendee_location.RecordLegacyLocation(
1750 field, DescriptorPool::ErrorCollector::EXTENDEE);
1751 is_first = false;
1752 }
1753 }
1754
1755 field->set_extendee(extendee);
1756
1757 if (!ParseMessageField(field, messages, parent_location,
1758 location_field_number_for_nested_type,
1759 location,
1760 containing_file)) {
1761 // This statement failed to parse. Skip it, but keep looping to parse
1762 // other statements.
1763 SkipStatement();
1764 }
1765 } while (!TryConsumeEndOfDeclaration("}", NULL));
1766
1767 return true;
1768}
1769
1770bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl,
1771 DescriptorProto* containing_type,
1772 int oneof_index,
1773 const LocationRecorder& oneof_location,
1774 const LocationRecorder& containing_type_location,
1775 const FileDescriptorProto* containing_file) {
1776 DO(Consume("oneof"));
1777
1778 {
1779 LocationRecorder name_location(oneof_location,
1780 OneofDescriptorProto::kNameFieldNumber);
1781 DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name."));
1782 }
1783
1784 DO(ConsumeEndOfDeclaration("{", &oneof_location));
1785
1786 do {
1787 if (AtEnd()) {
1788 AddError("Reached end of input in oneof definition (missing '}').");
1789 return false;
1790 }
1791
Austin Schuh40c16522018-10-28 20:27:54 -07001792 if (LookingAt("option")) {
1793 LocationRecorder option_location(
1794 oneof_location, OneofDescriptorProto::kOptionsFieldNumber);
1795 if (!ParseOption(oneof_decl->mutable_options(), option_location,
1796 containing_file, OPTION_STATEMENT)) {
1797 return false;
1798 }
1799 continue;
1800 }
1801
Brian Silverman9c614bc2016-02-15 20:20:02 -05001802 // Print a nice error if the user accidentally tries to place a label
1803 // on an individual member of a oneof.
1804 if (LookingAt("required") ||
1805 LookingAt("optional") ||
1806 LookingAt("repeated")) {
1807 AddError("Fields in oneofs must not have labels (required / optional "
1808 "/ repeated).");
1809 // We can continue parsing here because we understand what the user
1810 // meant. The error report will still make parsing fail overall.
1811 input_->Next();
1812 }
1813
1814 LocationRecorder field_location(containing_type_location,
1815 DescriptorProto::kFieldFieldNumber,
1816 containing_type->field_size());
1817
1818 FieldDescriptorProto* field = containing_type->add_field();
1819 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
1820 field->set_oneof_index(oneof_index);
1821
1822 if (!ParseMessageFieldNoLabel(field,
1823 containing_type->mutable_nested_type(),
1824 containing_type_location,
1825 DescriptorProto::kNestedTypeFieldNumber,
1826 field_location,
1827 containing_file)) {
1828 // This statement failed to parse. Skip it, but keep looping to parse
1829 // other statements.
1830 SkipStatement();
1831 }
1832 } while (!TryConsumeEndOfDeclaration("}", NULL));
1833
1834 return true;
1835}
1836
1837// -------------------------------------------------------------------
1838// Enums
1839
1840bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type,
1841 const LocationRecorder& enum_location,
1842 const FileDescriptorProto* containing_file) {
1843 DO(Consume("enum"));
1844
1845 {
1846 LocationRecorder location(enum_location,
1847 EnumDescriptorProto::kNameFieldNumber);
1848 location.RecordLegacyLocation(
1849 enum_type, DescriptorPool::ErrorCollector::NAME);
1850 DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name."));
1851 }
1852
1853 DO(ParseEnumBlock(enum_type, enum_location, containing_file));
1854
1855 DO(ValidateEnum(enum_type));
1856
1857 return true;
1858}
1859
1860bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type,
1861 const LocationRecorder& enum_location,
1862 const FileDescriptorProto* containing_file) {
1863 DO(ConsumeEndOfDeclaration("{", &enum_location));
1864
1865 while (!TryConsumeEndOfDeclaration("}", NULL)) {
1866 if (AtEnd()) {
1867 AddError("Reached end of input in enum definition (missing '}').");
1868 return false;
1869 }
1870
1871 if (!ParseEnumStatement(enum_type, enum_location, containing_file)) {
1872 // This statement failed to parse. Skip it, but keep looping to parse
1873 // other statements.
1874 SkipStatement();
1875 }
1876 }
1877
1878 return true;
1879}
1880
1881bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type,
1882 const LocationRecorder& enum_location,
1883 const FileDescriptorProto* containing_file) {
1884 if (TryConsumeEndOfDeclaration(";", NULL)) {
1885 // empty statement; ignore
1886 return true;
1887 } else if (LookingAt("option")) {
1888 LocationRecorder location(enum_location,
1889 EnumDescriptorProto::kOptionsFieldNumber);
1890 return ParseOption(enum_type->mutable_options(), location,
1891 containing_file, OPTION_STATEMENT);
Austin Schuh40c16522018-10-28 20:27:54 -07001892 } else if (LookingAt("reserved")) {
1893 return ParseReserved(enum_type, enum_location);
Brian Silverman9c614bc2016-02-15 20:20:02 -05001894 } else {
1895 LocationRecorder location(enum_location,
1896 EnumDescriptorProto::kValueFieldNumber, enum_type->value_size());
1897 return ParseEnumConstant(enum_type->add_value(), location, containing_file);
1898 }
1899}
1900
1901bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value,
1902 const LocationRecorder& enum_value_location,
1903 const FileDescriptorProto* containing_file) {
1904 // Parse name.
1905 {
1906 LocationRecorder location(enum_value_location,
1907 EnumValueDescriptorProto::kNameFieldNumber);
1908 location.RecordLegacyLocation(
1909 enum_value, DescriptorPool::ErrorCollector::NAME);
1910 DO(ConsumeIdentifier(enum_value->mutable_name(),
1911 "Expected enum constant name."));
1912 }
1913
1914 DO(Consume("=", "Missing numeric value for enum constant."));
1915
1916 // Parse value.
1917 {
1918 LocationRecorder location(
1919 enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber);
1920 location.RecordLegacyLocation(
1921 enum_value, DescriptorPool::ErrorCollector::NUMBER);
1922
1923 int number;
1924 DO(ConsumeSignedInteger(&number, "Expected integer."));
1925 enum_value->set_number(number);
1926 }
1927
1928 DO(ParseEnumConstantOptions(enum_value, enum_value_location,
1929 containing_file));
1930
1931 DO(ConsumeEndOfDeclaration(";", &enum_value_location));
1932
1933 return true;
1934}
1935
1936bool Parser::ParseEnumConstantOptions(
1937 EnumValueDescriptorProto* value,
1938 const LocationRecorder& enum_value_location,
1939 const FileDescriptorProto* containing_file) {
1940 if (!LookingAt("[")) return true;
1941
1942 LocationRecorder location(
1943 enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber);
1944
1945 DO(Consume("["));
1946
1947 do {
1948 DO(ParseOption(value->mutable_options(), location,
1949 containing_file, OPTION_ASSIGNMENT));
1950 } while (TryConsume(","));
1951
1952 DO(Consume("]"));
1953 return true;
1954}
1955
1956// -------------------------------------------------------------------
1957// Services
1958
1959bool Parser::ParseServiceDefinition(
1960 ServiceDescriptorProto* service,
1961 const LocationRecorder& service_location,
1962 const FileDescriptorProto* containing_file) {
1963 DO(Consume("service"));
1964
1965 {
1966 LocationRecorder location(service_location,
1967 ServiceDescriptorProto::kNameFieldNumber);
1968 location.RecordLegacyLocation(
1969 service, DescriptorPool::ErrorCollector::NAME);
1970 DO(ConsumeIdentifier(service->mutable_name(), "Expected service name."));
1971 }
1972
1973 DO(ParseServiceBlock(service, service_location, containing_file));
1974 return true;
1975}
1976
1977bool Parser::ParseServiceBlock(ServiceDescriptorProto* service,
1978 const LocationRecorder& service_location,
1979 const FileDescriptorProto* containing_file) {
1980 DO(ConsumeEndOfDeclaration("{", &service_location));
1981
1982 while (!TryConsumeEndOfDeclaration("}", NULL)) {
1983 if (AtEnd()) {
1984 AddError("Reached end of input in service definition (missing '}').");
1985 return false;
1986 }
1987
1988 if (!ParseServiceStatement(service, service_location, containing_file)) {
1989 // This statement failed to parse. Skip it, but keep looping to parse
1990 // other statements.
1991 SkipStatement();
1992 }
1993 }
1994
1995 return true;
1996}
1997
1998bool Parser::ParseServiceStatement(ServiceDescriptorProto* service,
1999 const LocationRecorder& service_location,
2000 const FileDescriptorProto* containing_file) {
2001 if (TryConsumeEndOfDeclaration(";", NULL)) {
2002 // empty statement; ignore
2003 return true;
2004 } else if (LookingAt("option")) {
2005 LocationRecorder location(
2006 service_location, ServiceDescriptorProto::kOptionsFieldNumber);
2007 return ParseOption(service->mutable_options(), location,
2008 containing_file, OPTION_STATEMENT);
2009 } else {
2010 LocationRecorder location(service_location,
2011 ServiceDescriptorProto::kMethodFieldNumber, service->method_size());
2012 return ParseServiceMethod(service->add_method(), location, containing_file);
2013 }
2014}
2015
2016bool Parser::ParseServiceMethod(MethodDescriptorProto* method,
2017 const LocationRecorder& method_location,
2018 const FileDescriptorProto* containing_file) {
2019 DO(Consume("rpc"));
2020
2021 {
2022 LocationRecorder location(method_location,
2023 MethodDescriptorProto::kNameFieldNumber);
2024 location.RecordLegacyLocation(
2025 method, DescriptorPool::ErrorCollector::NAME);
2026 DO(ConsumeIdentifier(method->mutable_name(), "Expected method name."));
2027 }
2028
2029 // Parse input type.
2030 DO(Consume("("));
2031 {
2032 if (LookingAt("stream")) {
2033 LocationRecorder location(
2034 method_location, MethodDescriptorProto::kClientStreamingFieldNumber);
2035 location.RecordLegacyLocation(
2036 method, DescriptorPool::ErrorCollector::OTHER);
2037 method->set_client_streaming(true);
2038 DO(Consume("stream"));
2039
2040 }
2041 LocationRecorder location(method_location,
2042 MethodDescriptorProto::kInputTypeFieldNumber);
2043 location.RecordLegacyLocation(
2044 method, DescriptorPool::ErrorCollector::INPUT_TYPE);
2045 DO(ParseUserDefinedType(method->mutable_input_type()));
2046 }
2047 DO(Consume(")"));
2048
2049 // Parse output type.
2050 DO(Consume("returns"));
2051 DO(Consume("("));
2052 {
2053 if (LookingAt("stream")) {
2054 LocationRecorder location(
2055 method_location, MethodDescriptorProto::kServerStreamingFieldNumber);
2056 location.RecordLegacyLocation(
2057 method, DescriptorPool::ErrorCollector::OTHER);
2058 DO(Consume("stream"));
2059 method->set_server_streaming(true);
2060
2061 }
2062 LocationRecorder location(method_location,
2063 MethodDescriptorProto::kOutputTypeFieldNumber);
2064 location.RecordLegacyLocation(
2065 method, DescriptorPool::ErrorCollector::OUTPUT_TYPE);
2066 DO(ParseUserDefinedType(method->mutable_output_type()));
2067 }
2068 DO(Consume(")"));
2069
2070 if (LookingAt("{")) {
2071 // Options!
2072 DO(ParseMethodOptions(method_location, containing_file,
2073 MethodDescriptorProto::kOptionsFieldNumber,
2074 method->mutable_options()));
2075 } else {
2076 DO(ConsumeEndOfDeclaration(";", &method_location));
2077 }
2078
2079 return true;
2080}
2081
2082
2083bool Parser::ParseMethodOptions(const LocationRecorder& parent_location,
2084 const FileDescriptorProto* containing_file,
2085 const int optionsFieldNumber,
2086 Message* mutable_options) {
2087 // Options!
2088 ConsumeEndOfDeclaration("{", &parent_location);
2089 while (!TryConsumeEndOfDeclaration("}", NULL)) {
2090 if (AtEnd()) {
2091 AddError("Reached end of input in method options (missing '}').");
2092 return false;
2093 }
2094
2095 if (TryConsumeEndOfDeclaration(";", NULL)) {
2096 // empty statement; ignore
2097 } else {
2098 LocationRecorder location(parent_location,
2099 optionsFieldNumber);
2100 if (!ParseOption(mutable_options, location,
2101 containing_file, OPTION_STATEMENT)) {
2102 // This statement failed to parse. Skip it, but keep looping to
2103 // parse other statements.
2104 SkipStatement();
2105 }
2106 }
2107 }
2108
2109 return true;
2110}
2111
2112// -------------------------------------------------------------------
2113
2114bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
2115 const FileDescriptorProto* containing_file) {
2116 if (TryConsume("optional")) {
2117 *label = FieldDescriptorProto::LABEL_OPTIONAL;
2118 return true;
2119 } else if (TryConsume("repeated")) {
2120 *label = FieldDescriptorProto::LABEL_REPEATED;
2121 return true;
2122 } else if (TryConsume("required")) {
2123 *label = FieldDescriptorProto::LABEL_REQUIRED;
2124 return true;
2125 }
2126 return false;
2127}
2128
2129bool Parser::ParseType(FieldDescriptorProto::Type* type,
2130 string* type_name) {
2131 TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
2132 if (iter != kTypeNames.end()) {
2133 *type = iter->second;
2134 input_->Next();
2135 } else {
2136 DO(ParseUserDefinedType(type_name));
2137 }
2138 return true;
2139}
2140
2141bool Parser::ParseUserDefinedType(string* type_name) {
2142 type_name->clear();
2143
2144 TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text);
2145 if (iter != kTypeNames.end()) {
2146 // Note: The only place enum types are allowed is for field types, but
2147 // if we are parsing a field type then we would not get here because
2148 // primitives are allowed there as well. So this error message doesn't
2149 // need to account for enums.
2150 AddError("Expected message type.");
2151
2152 // Pretend to accept this type so that we can go on parsing.
2153 *type_name = input_->current().text;
2154 input_->Next();
2155 return true;
2156 }
2157
2158 // A leading "." means the name is fully-qualified.
2159 if (TryConsume(".")) type_name->append(".");
2160
2161 // Consume the first part of the name.
2162 string identifier;
2163 DO(ConsumeIdentifier(&identifier, "Expected type name."));
2164 type_name->append(identifier);
2165
2166 // Consume more parts.
2167 while (TryConsume(".")) {
2168 type_name->append(".");
2169 DO(ConsumeIdentifier(&identifier, "Expected identifier."));
2170 type_name->append(identifier);
2171 }
2172
2173 return true;
2174}
2175
2176// ===================================================================
2177
2178bool Parser::ParsePackage(FileDescriptorProto* file,
2179 const LocationRecorder& root_location,
2180 const FileDescriptorProto* containing_file) {
2181 if (file->has_package()) {
2182 AddError("Multiple package definitions.");
2183 // Don't append the new package to the old one. Just replace it. Not
2184 // that it really matters since this is an error anyway.
2185 file->clear_package();
2186 }
2187
2188 DO(Consume("package"));
2189
2190 {
2191 LocationRecorder location(root_location,
2192 FileDescriptorProto::kPackageFieldNumber);
2193 location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME);
2194
2195 while (true) {
2196 string identifier;
2197 DO(ConsumeIdentifier(&identifier, "Expected identifier."));
2198 file->mutable_package()->append(identifier);
2199 if (!TryConsume(".")) break;
2200 file->mutable_package()->append(".");
2201 }
2202
2203 location.EndAt(input_->previous());
2204
2205 DO(ConsumeEndOfDeclaration(";", &location));
2206 }
2207
2208 return true;
2209}
2210
2211bool Parser::ParseImport(RepeatedPtrField<string>* dependency,
2212 RepeatedField<int32>* public_dependency,
2213 RepeatedField<int32>* weak_dependency,
2214 const LocationRecorder& root_location,
2215 const FileDescriptorProto* containing_file) {
2216 DO(Consume("import"));
2217 if (LookingAt("public")) {
2218 LocationRecorder location(
2219 root_location, FileDescriptorProto::kPublicDependencyFieldNumber,
2220 public_dependency->size());
2221 DO(Consume("public"));
2222 *public_dependency->Add() = dependency->size();
2223 } else if (LookingAt("weak")) {
2224 LocationRecorder location(
2225 root_location, FileDescriptorProto::kWeakDependencyFieldNumber,
2226 weak_dependency->size());
2227 DO(Consume("weak"));
2228 *weak_dependency->Add() = dependency->size();
2229 }
2230 {
2231 LocationRecorder location(root_location,
2232 FileDescriptorProto::kDependencyFieldNumber,
2233 dependency->size());
2234 DO(ConsumeString(dependency->Add(),
2235 "Expected a string naming the file to import."));
2236
2237 location.EndAt(input_->previous());
2238
2239 DO(ConsumeEndOfDeclaration(";", &location));
2240 }
2241 return true;
2242}
2243
2244// ===================================================================
2245
2246SourceLocationTable::SourceLocationTable() {}
2247SourceLocationTable::~SourceLocationTable() {}
2248
2249bool SourceLocationTable::Find(
2250 const Message* descriptor,
2251 DescriptorPool::ErrorCollector::ErrorLocation location,
2252 int* line, int* column) const {
Austin Schuh40c16522018-10-28 20:27:54 -07002253 const std::pair<int, int>* result =
Brian Silverman9c614bc2016-02-15 20:20:02 -05002254 FindOrNull(location_map_, std::make_pair(descriptor, location));
2255 if (result == NULL) {
2256 *line = -1;
2257 *column = 0;
2258 return false;
2259 } else {
2260 *line = result->first;
2261 *column = result->second;
2262 return true;
2263 }
2264}
2265
2266void SourceLocationTable::Add(
2267 const Message* descriptor,
2268 DescriptorPool::ErrorCollector::ErrorLocation location,
2269 int line, int column) {
2270 location_map_[std::make_pair(descriptor, location)] =
2271 std::make_pair(line, column);
2272}
2273
2274void SourceLocationTable::Clear() {
2275 location_map_.clear();
2276}
2277
2278} // namespace compiler
2279} // namespace protobuf
Austin Schuh40c16522018-10-28 20:27:54 -07002280
Brian Silverman9c614bc2016-02-15 20:20:02 -05002281} // namespace google