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