OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // http://code.google.com/p/protobuf/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
11 // * Redistributions in binary form must reproduce the above | 11 // * Redistributions in binary form must reproduce the above |
12 // copyright notice, this list of conditions and the following disclaimer | 12 // copyright notice, this list of conditions and the following disclaimer |
13 // in the documentation and/or other materials provided with the | 13 // in the documentation and/or other materials provided with the |
(...skipping 23 matching lines...) Expand all Loading... |
37 #include <float.h> | 37 #include <float.h> |
38 #include <google/protobuf/stubs/hash.h> | 38 #include <google/protobuf/stubs/hash.h> |
39 #include <limits> | 39 #include <limits> |
40 | 40 |
41 | 41 |
42 #include <google/protobuf/compiler/parser.h> | 42 #include <google/protobuf/compiler/parser.h> |
43 #include <google/protobuf/descriptor.h> | 43 #include <google/protobuf/descriptor.h> |
44 #include <google/protobuf/descriptor.pb.h> | 44 #include <google/protobuf/descriptor.pb.h> |
45 #include <google/protobuf/wire_format.h> | 45 #include <google/protobuf/wire_format.h> |
46 #include <google/protobuf/io/tokenizer.h> | 46 #include <google/protobuf/io/tokenizer.h> |
| 47 #include <google/protobuf/stubs/logging.h> |
47 #include <google/protobuf/stubs/common.h> | 48 #include <google/protobuf/stubs/common.h> |
48 #include <google/protobuf/stubs/strutil.h> | 49 #include <google/protobuf/stubs/strutil.h> |
49 #include <google/protobuf/stubs/map-util.h> | 50 #include <google/protobuf/stubs/map_util.h> |
50 | 51 |
51 namespace google { | 52 namespace google { |
52 namespace protobuf { | 53 namespace protobuf { |
53 namespace compiler { | 54 namespace compiler { |
54 | 55 |
55 using internal::WireFormat; | 56 using internal::WireFormat; |
56 | 57 |
57 namespace { | 58 namespace { |
58 | 59 |
59 typedef hash_map<string, FieldDescriptorProto::Type> TypeNameMap; | 60 typedef hash_map<string, FieldDescriptorProto::Type> TypeNameMap; |
(...skipping 17 matching lines...) Expand all Loading... |
77 result["int32" ] = FieldDescriptorProto::TYPE_INT32; | 78 result["int32" ] = FieldDescriptorProto::TYPE_INT32; |
78 result["int64" ] = FieldDescriptorProto::TYPE_INT64; | 79 result["int64" ] = FieldDescriptorProto::TYPE_INT64; |
79 result["sint32" ] = FieldDescriptorProto::TYPE_SINT32; | 80 result["sint32" ] = FieldDescriptorProto::TYPE_SINT32; |
80 result["sint64" ] = FieldDescriptorProto::TYPE_SINT64; | 81 result["sint64" ] = FieldDescriptorProto::TYPE_SINT64; |
81 | 82 |
82 return result; | 83 return result; |
83 } | 84 } |
84 | 85 |
85 const TypeNameMap kTypeNames = MakeTypeNameTable(); | 86 const TypeNameMap kTypeNames = MakeTypeNameTable(); |
86 | 87 |
| 88 // Camel-case the field name and append "Entry" for generated map entry name. |
| 89 // e.g. map<KeyType, ValueType> foo_map => FooMapEntry |
| 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 |
87 } // anonymous namespace | 114 } // anonymous namespace |
88 | 115 |
89 // Makes code slightly more readable. The meaning of "DO(foo)" is | 116 // Makes code slightly more readable. The meaning of "DO(foo)" is |
90 // "Execute foo and fail if it fails.", where failure is indicated by | 117 // "Execute foo and fail if it fails.", where failure is indicated by |
91 // returning false. | 118 // returning false. |
92 #define DO(STATEMENT) if (STATEMENT) {} else return false | 119 #define DO(STATEMENT) if (STATEMENT) {} else return false |
93 | 120 |
94 // =================================================================== | 121 // =================================================================== |
95 | 122 |
96 Parser::Parser() | 123 Parser::Parser() |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 io::Tokenizer::ParseStringAppend(input_->current().text, output); | 271 io::Tokenizer::ParseStringAppend(input_->current().text, output); |
245 input_->Next(); | 272 input_->Next(); |
246 } | 273 } |
247 return true; | 274 return true; |
248 } else { | 275 } else { |
249 AddError(error); | 276 AddError(error); |
250 return false; | 277 return false; |
251 } | 278 } |
252 } | 279 } |
253 | 280 |
254 bool Parser::TryConsumeEndOfDeclaration(const char* text, | 281 bool Parser::TryConsumeEndOfDeclaration( |
255 const LocationRecorder* location) { | 282 const char* text, const LocationRecorder* location) { |
256 if (LookingAt(text)) { | 283 if (LookingAt(text)) { |
257 string leading, trailing; | 284 string leading, trailing; |
258 input_->NextWithComments(&trailing, NULL, &leading); | 285 vector<string> detached; |
| 286 input_->NextWithComments(&trailing, &detached, &leading); |
259 | 287 |
260 // Save the leading comments for next time, and recall the leading comments | 288 // Save the leading comments for next time, and recall the leading comments |
261 // from last time. | 289 // from last time. |
262 leading.swap(upcoming_doc_comments_); | 290 leading.swap(upcoming_doc_comments_); |
263 | 291 |
264 if (location != NULL) { | 292 if (location != NULL) { |
265 location->AttachComments(&leading, &trailing); | 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()); |
266 } | 304 } |
| 305 |
267 return true; | 306 return true; |
268 } else { | 307 } else { |
269 return false; | 308 return false; |
270 } | 309 } |
271 } | 310 } |
272 | 311 |
273 bool Parser::ConsumeEndOfDeclaration(const char* text, | 312 bool Parser::ConsumeEndOfDeclaration( |
274 const LocationRecorder* location) { | 313 const char* text, const LocationRecorder* location) { |
275 if (TryConsumeEndOfDeclaration(text, location)) { | 314 if (TryConsumeEndOfDeclaration(text, location)) { |
276 return true; | 315 return true; |
277 } else { | 316 } else { |
278 AddError("Expected \"" + string(text) + "\"."); | 317 AddError("Expected \"" + string(text) + "\"."); |
279 return false; | 318 return false; |
280 } | 319 } |
281 } | 320 } |
282 | 321 |
283 // ------------------------------------------------------------------- | 322 // ------------------------------------------------------------------- |
284 | 323 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 | 375 |
337 void Parser::LocationRecorder::AddPath(int path_component) { | 376 void Parser::LocationRecorder::AddPath(int path_component) { |
338 location_->add_path(path_component); | 377 location_->add_path(path_component); |
339 } | 378 } |
340 | 379 |
341 void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { | 380 void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { |
342 location_->set_span(0, token.line); | 381 location_->set_span(0, token.line); |
343 location_->set_span(1, token.column); | 382 location_->set_span(1, token.column); |
344 } | 383 } |
345 | 384 |
| 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 |
346 void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { | 390 void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { |
347 if (token.line != location_->span(0)) { | 391 if (token.line != location_->span(0)) { |
348 location_->add_span(token.line); | 392 location_->add_span(token.line); |
349 } | 393 } |
350 location_->add_span(token.end_column); | 394 location_->add_span(token.end_column); |
351 } | 395 } |
352 | 396 |
353 void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, | 397 void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, |
354 DescriptorPool::ErrorCollector::ErrorLocation location) { | 398 DescriptorPool::ErrorCollector::ErrorLocation location) { |
355 if (parser_->source_location_table_ != NULL) { | 399 if (parser_->source_location_table_ != NULL) { |
356 parser_->source_location_table_->Add( | 400 parser_->source_location_table_->Add( |
357 descriptor, location, location_->span(0), location_->span(1)); | 401 descriptor, location, location_->span(0), location_->span(1)); |
358 } | 402 } |
359 } | 403 } |
360 | 404 |
361 void Parser::LocationRecorder::AttachComments( | 405 void Parser::LocationRecorder::AttachComments( |
362 string* leading, string* trailing) const { | 406 string* leading, string* trailing, |
| 407 vector<string>* detached_comments) const { |
363 GOOGLE_CHECK(!location_->has_leading_comments()); | 408 GOOGLE_CHECK(!location_->has_leading_comments()); |
364 GOOGLE_CHECK(!location_->has_trailing_comments()); | 409 GOOGLE_CHECK(!location_->has_trailing_comments()); |
365 | 410 |
366 if (!leading->empty()) { | 411 if (!leading->empty()) { |
367 location_->mutable_leading_comments()->swap(*leading); | 412 location_->mutable_leading_comments()->swap(*leading); |
368 } | 413 } |
369 if (!trailing->empty()) { | 414 if (!trailing->empty()) { |
370 location_->mutable_trailing_comments()->swap(*trailing); | 415 location_->mutable_trailing_comments()->swap(*trailing); |
371 } | 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(); |
372 } | 422 } |
373 | 423 |
374 // ------------------------------------------------------------------- | 424 // ------------------------------------------------------------------- |
375 | 425 |
376 void Parser::SkipStatement() { | 426 void Parser::SkipStatement() { |
377 while (true) { | 427 while (true) { |
378 if (AtEnd()) { | 428 if (AtEnd()) { |
379 return; | 429 return; |
380 } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { | 430 } else if (LookingAtType(io::Tokenizer::TYPE_SYMBOL)) { |
381 if (TryConsumeEndOfDeclaration(";", NULL)) { | 431 if (TryConsumeEndOfDeclaration(";", NULL)) { |
(...skipping 19 matching lines...) Expand all Loading... |
401 } else if (TryConsume("{")) { | 451 } else if (TryConsume("{")) { |
402 SkipRestOfBlock(); | 452 SkipRestOfBlock(); |
403 } | 453 } |
404 } | 454 } |
405 input_->Next(); | 455 input_->Next(); |
406 } | 456 } |
407 } | 457 } |
408 | 458 |
409 // =================================================================== | 459 // =================================================================== |
410 | 460 |
| 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 |
411 bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { | 516 bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { |
412 input_ = input; | 517 input_ = input; |
413 had_errors_ = false; | 518 had_errors_ = false; |
414 syntax_identifier_.clear(); | 519 syntax_identifier_.clear(); |
415 | 520 |
416 // Note that |file| could be NULL at this point if | 521 // Note that |file| could be NULL at this point if |
417 // stop_after_syntax_identifier_ is true. So, we conservatively allocate | 522 // stop_after_syntax_identifier_ is true. So, we conservatively allocate |
418 // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto | 523 // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto |
419 // later on. | 524 // later on. |
420 SourceCodeInfo source_code_info; | 525 SourceCodeInfo source_code_info; |
421 source_code_info_ = &source_code_info; | 526 source_code_info_ = &source_code_info; |
422 | 527 |
| 528 vector<string> top_doc_comments; |
423 if (LookingAtType(io::Tokenizer::TYPE_START)) { | 529 if (LookingAtType(io::Tokenizer::TYPE_START)) { |
424 // Advance to first token. | 530 // Advance to first token. |
425 input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); | 531 input_->NextWithComments(NULL, &upcoming_detached_comments_, |
| 532 &upcoming_doc_comments_); |
426 } | 533 } |
427 | 534 |
428 { | 535 { |
429 LocationRecorder root_location(this); | 536 LocationRecorder root_location(this); |
430 | 537 |
431 if (require_syntax_identifier_ || LookingAt("syntax")) { | 538 if (require_syntax_identifier_ || LookingAt("syntax")) { |
432 if (!ParseSyntaxIdentifier()) { | 539 if (!ParseSyntaxIdentifier(root_location)) { |
433 // Don't attempt to parse the file if we didn't recognize the syntax | 540 // Don't attempt to parse the file if we didn't recognize the syntax |
434 // identifier. | 541 // identifier. |
435 return false; | 542 return false; |
436 } | 543 } |
| 544 // Store the syntax into the file. |
| 545 if (file != NULL) file->set_syntax(syntax_identifier_); |
437 } else if (!stop_after_syntax_identifier_) { | 546 } else if (!stop_after_syntax_identifier_) { |
| 547 GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. " |
| 548 << "Please use 'syntax = \"proto2\";' or " |
| 549 << "'syntax = \"proto3\";' to specify a syntax " |
| 550 << "version. (Defaulted to proto2 syntax.)"; |
438 syntax_identifier_ = "proto2"; | 551 syntax_identifier_ = "proto2"; |
439 } | 552 } |
440 | 553 |
441 if (stop_after_syntax_identifier_) return !had_errors_; | 554 if (stop_after_syntax_identifier_) return !had_errors_; |
442 | 555 |
443 // Repeatedly parse statements until we reach the end of the file. | 556 // Repeatedly parse statements until we reach the end of the file. |
444 while (!AtEnd()) { | 557 while (!AtEnd()) { |
445 if (!ParseTopLevelStatement(file, root_location)) { | 558 if (!ParseTopLevelStatement(file, root_location)) { |
446 // This statement failed to parse. Skip it, but keep looping to parse | 559 // This statement failed to parse. Skip it, but keep looping to parse |
447 // other statements. | 560 // other statements. |
448 SkipStatement(); | 561 SkipStatement(); |
449 | 562 |
450 if (LookingAt("}")) { | 563 if (LookingAt("}")) { |
451 AddError("Unmatched \"}\"."); | 564 AddError("Unmatched \"}\"."); |
452 input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); | 565 input_->NextWithComments(NULL, &upcoming_detached_comments_, |
| 566 &upcoming_doc_comments_); |
453 } | 567 } |
454 } | 568 } |
455 } | 569 } |
456 } | 570 } |
457 | 571 |
458 input_ = NULL; | 572 input_ = NULL; |
459 source_code_info_ = NULL; | 573 source_code_info_ = NULL; |
460 source_code_info.Swap(file->mutable_source_code_info()); | 574 source_code_info.Swap(file->mutable_source_code_info()); |
461 return !had_errors_; | 575 return !had_errors_; |
462 } | 576 } |
463 | 577 |
464 bool Parser::ParseSyntaxIdentifier() { | 578 bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { |
465 DO(Consume("syntax", "File must begin with 'syntax = \"proto2\";'.")); | 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\";'.")); |
466 DO(Consume("=")); | 584 DO(Consume("=")); |
467 io::Tokenizer::Token syntax_token = input_->current(); | 585 io::Tokenizer::Token syntax_token = input_->current(); |
468 string syntax; | 586 string syntax; |
469 DO(ConsumeString(&syntax, "Expected syntax identifier.")); | 587 DO(ConsumeString(&syntax, "Expected syntax identifier.")); |
470 DO(ConsumeEndOfDeclaration(";", NULL)); | 588 DO(ConsumeEndOfDeclaration(";", &syntax_location)); |
471 | 589 |
472 syntax_identifier_ = syntax; | 590 syntax_identifier_ = syntax; |
473 | 591 |
474 if (syntax != "proto2" && !stop_after_syntax_identifier_) { | 592 if (syntax != "proto2" && syntax != "proto3" && |
| 593 !stop_after_syntax_identifier_) { |
475 AddError(syntax_token.line, syntax_token.column, | 594 AddError(syntax_token.line, syntax_token.column, |
476 "Unrecognized syntax identifier \"" + syntax + "\". This parser " | 595 "Unrecognized syntax identifier \"" + syntax + "\". This parser " |
477 "only recognizes \"proto2\"."); | 596 "only recognizes \"proto2\" and \"proto3\"."); |
478 return false; | 597 return false; |
479 } | 598 } |
480 | 599 |
481 return true; | 600 return true; |
482 } | 601 } |
483 | 602 |
484 bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, | 603 bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, |
485 const LocationRecorder& root_location) { | 604 const LocationRecorder& root_location) { |
486 if (TryConsumeEndOfDeclaration(";", NULL)) { | 605 if (TryConsumeEndOfDeclaration(";", NULL)) { |
487 // empty statement; ignore | 606 // empty statement; ignore |
488 return true; | 607 return true; |
489 } else if (LookingAt("message")) { | 608 } else if (LookingAt("message")) { |
490 LocationRecorder location(root_location, | 609 LocationRecorder location(root_location, |
491 FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); | 610 FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); |
492 return ParseMessageDefinition(file->add_message_type(), location); | 611 return ParseMessageDefinition(file->add_message_type(), location, file); |
493 } else if (LookingAt("enum")) { | 612 } else if (LookingAt("enum")) { |
494 LocationRecorder location(root_location, | 613 LocationRecorder location(root_location, |
495 FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); | 614 FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); |
496 return ParseEnumDefinition(file->add_enum_type(), location); | 615 return ParseEnumDefinition(file->add_enum_type(), location, file); |
497 } else if (LookingAt("service")) { | 616 } else if (LookingAt("service")) { |
498 LocationRecorder location(root_location, | 617 LocationRecorder location(root_location, |
499 FileDescriptorProto::kServiceFieldNumber, file->service_size()); | 618 FileDescriptorProto::kServiceFieldNumber, file->service_size()); |
500 return ParseServiceDefinition(file->add_service(), location); | 619 return ParseServiceDefinition(file->add_service(), location, file); |
501 } else if (LookingAt("extend")) { | 620 } else if (LookingAt("extend")) { |
502 LocationRecorder location(root_location, | 621 LocationRecorder location(root_location, |
503 FileDescriptorProto::kExtensionFieldNumber); | 622 FileDescriptorProto::kExtensionFieldNumber); |
504 return ParseExtend(file->mutable_extension(), | 623 return ParseExtend(file->mutable_extension(), |
505 file->mutable_message_type(), | 624 file->mutable_message_type(), |
506 root_location, | 625 root_location, |
507 FileDescriptorProto::kMessageTypeFieldNumber, | 626 FileDescriptorProto::kMessageTypeFieldNumber, |
508 location); | 627 location, file); |
509 } else if (LookingAt("import")) { | 628 } else if (LookingAt("import")) { |
510 return ParseImport(file->mutable_dependency(), | 629 return ParseImport(file->mutable_dependency(), |
511 file->mutable_public_dependency(), | 630 file->mutable_public_dependency(), |
512 file->mutable_weak_dependency(), | 631 file->mutable_weak_dependency(), |
513 root_location); | 632 root_location, file); |
514 } else if (LookingAt("package")) { | 633 } else if (LookingAt("package")) { |
515 return ParsePackage(file, root_location); | 634 return ParsePackage(file, root_location, file); |
516 } else if (LookingAt("option")) { | 635 } else if (LookingAt("option")) { |
517 LocationRecorder location(root_location, | 636 LocationRecorder location(root_location, |
518 FileDescriptorProto::kOptionsFieldNumber); | 637 FileDescriptorProto::kOptionsFieldNumber); |
519 return ParseOption(file->mutable_options(), location, OPTION_STATEMENT); | 638 return ParseOption(file->mutable_options(), location, file, |
| 639 OPTION_STATEMENT); |
520 } else { | 640 } else { |
521 AddError("Expected top-level statement (e.g. \"message\")."); | 641 AddError("Expected top-level statement (e.g. \"message\")."); |
522 return false; | 642 return false; |
523 } | 643 } |
524 } | 644 } |
525 | 645 |
526 // ------------------------------------------------------------------- | 646 // ------------------------------------------------------------------- |
527 // Messages | 647 // Messages |
528 | 648 |
529 bool Parser::ParseMessageDefinition(DescriptorProto* message, | 649 bool Parser::ParseMessageDefinition( |
530 const LocationRecorder& message_location) { | 650 DescriptorProto* message, |
| 651 const LocationRecorder& message_location, |
| 652 const FileDescriptorProto* containing_file) { |
531 DO(Consume("message")); | 653 DO(Consume("message")); |
532 { | 654 { |
533 LocationRecorder location(message_location, | 655 LocationRecorder location(message_location, |
534 DescriptorProto::kNameFieldNumber); | 656 DescriptorProto::kNameFieldNumber); |
535 location.RecordLegacyLocation( | 657 location.RecordLegacyLocation( |
536 message, DescriptorPool::ErrorCollector::NAME); | 658 message, DescriptorPool::ErrorCollector::NAME); |
537 DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); | 659 DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); |
538 } | 660 } |
539 DO(ParseMessageBlock(message, message_location)); | 661 DO(ParseMessageBlock(message, message_location, containing_file)); |
540 return true; | 662 return true; |
541 } | 663 } |
542 | 664 |
543 namespace { | 665 namespace { |
544 | 666 |
545 const int kMaxExtensionRangeSentinel = -1; | 667 const int kMaxExtensionRangeSentinel = -1; |
546 | 668 |
547 bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { | 669 bool IsMessageSetWireFormatMessage(const DescriptorProto& message) { |
548 const MessageOptions& options = message.options(); | 670 const MessageOptions& options = message.options(); |
549 for (int i = 0; i < options.uninterpreted_option_size(); ++i) { | 671 for (int i = 0; i < options.uninterpreted_option_size(); ++i) { |
(...skipping 18 matching lines...) Expand all Loading... |
568 for (int i = 0; i < message->extension_range_size(); ++i) { | 690 for (int i = 0; i < message->extension_range_size(); ++i) { |
569 if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) { | 691 if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) { |
570 message->mutable_extension_range(i)->set_end(max_extension_number); | 692 message->mutable_extension_range(i)->set_end(max_extension_number); |
571 } | 693 } |
572 } | 694 } |
573 } | 695 } |
574 | 696 |
575 } // namespace | 697 } // namespace |
576 | 698 |
577 bool Parser::ParseMessageBlock(DescriptorProto* message, | 699 bool Parser::ParseMessageBlock(DescriptorProto* message, |
578 const LocationRecorder& message_location) { | 700 const LocationRecorder& message_location, |
| 701 const FileDescriptorProto* containing_file) { |
579 DO(ConsumeEndOfDeclaration("{", &message_location)); | 702 DO(ConsumeEndOfDeclaration("{", &message_location)); |
580 | 703 |
581 while (!TryConsumeEndOfDeclaration("}", NULL)) { | 704 while (!TryConsumeEndOfDeclaration("}", NULL)) { |
582 if (AtEnd()) { | 705 if (AtEnd()) { |
583 AddError("Reached end of input in message definition (missing '}')."); | 706 AddError("Reached end of input in message definition (missing '}')."); |
584 return false; | 707 return false; |
585 } | 708 } |
586 | 709 |
587 if (!ParseMessageStatement(message, message_location)) { | 710 if (!ParseMessageStatement(message, message_location, containing_file)) { |
588 // This statement failed to parse. Skip it, but keep looping to parse | 711 // This statement failed to parse. Skip it, but keep looping to parse |
589 // other statements. | 712 // other statements. |
590 SkipStatement(); | 713 SkipStatement(); |
591 } | 714 } |
592 } | 715 } |
593 | 716 |
594 if (message->extension_range_size() > 0) { | 717 if (message->extension_range_size() > 0) { |
595 AdjustExtensionRangesWithMaxEndNumber(message); | 718 AdjustExtensionRangesWithMaxEndNumber(message); |
596 } | 719 } |
597 return true; | 720 return true; |
598 } | 721 } |
599 | 722 |
600 bool Parser::ParseMessageStatement(DescriptorProto* message, | 723 bool Parser::ParseMessageStatement(DescriptorProto* message, |
601 const LocationRecorder& message_location) { | 724 const LocationRecorder& message_location, |
| 725 const FileDescriptorProto* containing_file) { |
602 if (TryConsumeEndOfDeclaration(";", NULL)) { | 726 if (TryConsumeEndOfDeclaration(";", NULL)) { |
603 // empty statement; ignore | 727 // empty statement; ignore |
604 return true; | 728 return true; |
605 } else if (LookingAt("message")) { | 729 } else if (LookingAt("message")) { |
606 LocationRecorder location(message_location, | 730 LocationRecorder location(message_location, |
607 DescriptorProto::kNestedTypeFieldNumber, | 731 DescriptorProto::kNestedTypeFieldNumber, |
608 message->nested_type_size()); | 732 message->nested_type_size()); |
609 return ParseMessageDefinition(message->add_nested_type(), location); | 733 return ParseMessageDefinition(message->add_nested_type(), location, |
| 734 containing_file); |
610 } else if (LookingAt("enum")) { | 735 } else if (LookingAt("enum")) { |
611 LocationRecorder location(message_location, | 736 LocationRecorder location(message_location, |
612 DescriptorProto::kEnumTypeFieldNumber, | 737 DescriptorProto::kEnumTypeFieldNumber, |
613 message->enum_type_size()); | 738 message->enum_type_size()); |
614 return ParseEnumDefinition(message->add_enum_type(), location); | 739 return ParseEnumDefinition(message->add_enum_type(), location, |
| 740 containing_file); |
615 } else if (LookingAt("extensions")) { | 741 } else if (LookingAt("extensions")) { |
616 LocationRecorder location(message_location, | 742 LocationRecorder location(message_location, |
617 DescriptorProto::kExtensionRangeFieldNumber); | 743 DescriptorProto::kExtensionRangeFieldNumber); |
618 return ParseExtensions(message, location); | 744 return ParseExtensions(message, location, containing_file); |
| 745 } else if (LookingAt("reserved")) { |
| 746 return ParseReserved(message, message_location); |
619 } else if (LookingAt("extend")) { | 747 } else if (LookingAt("extend")) { |
620 LocationRecorder location(message_location, | 748 LocationRecorder location(message_location, |
621 DescriptorProto::kExtensionFieldNumber); | 749 DescriptorProto::kExtensionFieldNumber); |
622 return ParseExtend(message->mutable_extension(), | 750 return ParseExtend(message->mutable_extension(), |
623 message->mutable_nested_type(), | 751 message->mutable_nested_type(), |
624 message_location, | 752 message_location, |
625 DescriptorProto::kNestedTypeFieldNumber, | 753 DescriptorProto::kNestedTypeFieldNumber, |
626 location); | 754 location, containing_file); |
627 } else if (LookingAt("option")) { | 755 } else if (LookingAt("option")) { |
628 LocationRecorder location(message_location, | 756 LocationRecorder location(message_location, |
629 DescriptorProto::kOptionsFieldNumber); | 757 DescriptorProto::kOptionsFieldNumber); |
630 return ParseOption(message->mutable_options(), location, OPTION_STATEMENT); | 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); |
631 } else { | 769 } else { |
632 LocationRecorder location(message_location, | 770 LocationRecorder location(message_location, |
633 DescriptorProto::kFieldFieldNumber, | 771 DescriptorProto::kFieldFieldNumber, |
634 message->field_size()); | 772 message->field_size()); |
635 return ParseMessageField(message->add_field(), | 773 return ParseMessageField(message->add_field(), |
636 message->mutable_nested_type(), | 774 message->mutable_nested_type(), |
637 message_location, | 775 message_location, |
638 DescriptorProto::kNestedTypeFieldNumber, | 776 DescriptorProto::kNestedTypeFieldNumber, |
639 location); | 777 location, |
| 778 containing_file); |
640 } | 779 } |
641 } | 780 } |
642 | 781 |
643 bool Parser::ParseMessageField(FieldDescriptorProto* field, | 782 bool Parser::ParseMessageField(FieldDescriptorProto* field, |
644 RepeatedPtrField<DescriptorProto>* messages, | 783 RepeatedPtrField<DescriptorProto>* messages, |
645 const LocationRecorder& parent_location, | 784 const LocationRecorder& parent_location, |
646 int location_field_number_for_nested_type, | 785 int location_field_number_for_nested_type, |
647 const LocationRecorder& field_location) { | 786 const LocationRecorder& field_location, |
648 // Parse label and type. | 787 const FileDescriptorProto* containing_file) { |
649 io::Tokenizer::Token label_token = input_->current(); | |
650 { | 788 { |
651 LocationRecorder location(field_location, | 789 LocationRecorder location(field_location, |
652 FieldDescriptorProto::kLabelFieldNumber); | 790 FieldDescriptorProto::kLabelFieldNumber); |
653 FieldDescriptorProto::Label label; | 791 FieldDescriptorProto::Label label; |
654 DO(ParseLabel(&label)); | 792 if (ParseLabel(&label, containing_file)) { |
655 field->set_label(label); | 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 } |
656 } | 802 } |
657 | 803 |
| 804 return ParseMessageFieldNoLabel(field, messages, parent_location, |
| 805 location_field_number_for_nested_type, |
| 806 field_location, |
| 807 containing_file); |
| 808 } |
| 809 |
| 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. |
658 { | 819 { |
659 LocationRecorder location(field_location); // add path later | 820 LocationRecorder location(field_location); // add path later |
660 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); | 821 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); |
661 | 822 |
| 823 bool type_parsed = false; |
662 FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; | 824 FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; |
663 string type_name; | 825 string type_name; |
664 DO(ParseType(&type, &type_name)); | 826 |
665 if (type_name.empty()) { | 827 // Special case map field. We only treat the field as a map field if the |
666 location.AddPath(FieldDescriptorProto::kTypeFieldNumber); | 828 // field type name starts with the word "map" with a following "<". |
667 field->set_type(type); | 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); |
668 } else { | 862 } else { |
669 location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber); | 863 // Handle the case where no explicit label is given for a non-map field. |
670 field->set_type_name(type_name); | 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 } |
671 } | 886 } |
672 } | 887 } |
673 | 888 |
674 // Parse name and '='. | 889 // Parse name and '='. |
675 io::Tokenizer::Token name_token = input_->current(); | 890 io::Tokenizer::Token name_token = input_->current(); |
676 { | 891 { |
677 LocationRecorder location(field_location, | 892 LocationRecorder location(field_location, |
678 FieldDescriptorProto::kNameFieldNumber); | 893 FieldDescriptorProto::kNameFieldNumber); |
679 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); | 894 location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); |
680 DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); | 895 DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); |
681 } | 896 } |
682 DO(Consume("=", "Missing field number.")); | 897 DO(Consume("=", "Missing field number.")); |
683 | 898 |
684 // Parse field number. | 899 // Parse field number. |
685 { | 900 { |
686 LocationRecorder location(field_location, | 901 LocationRecorder location(field_location, |
687 FieldDescriptorProto::kNumberFieldNumber); | 902 FieldDescriptorProto::kNumberFieldNumber); |
688 location.RecordLegacyLocation( | 903 location.RecordLegacyLocation( |
689 field, DescriptorPool::ErrorCollector::NUMBER); | 904 field, DescriptorPool::ErrorCollector::NUMBER); |
690 int number; | 905 int number; |
691 DO(ConsumeInteger(&number, "Expected field number.")); | 906 DO(ConsumeInteger(&number, "Expected field number.")); |
692 field->set_number(number); | 907 field->set_number(number); |
693 } | 908 } |
694 | 909 |
695 // Parse options. | 910 // Parse options. |
696 DO(ParseFieldOptions(field, field_location)); | 911 DO(ParseFieldOptions(field, field_location, containing_file)); |
697 | 912 |
698 // Deal with groups. | 913 // Deal with groups. |
699 if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { | 914 if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { |
700 // Awkward: Since a group declares both a message type and a field, we | 915 // Awkward: Since a group declares both a message type and a field, we |
701 // have to create overlapping locations. | 916 // have to create overlapping locations. |
702 LocationRecorder group_location(parent_location); | 917 LocationRecorder group_location(parent_location); |
703 group_location.StartAt(label_token); | 918 group_location.StartAt(field_location); |
704 group_location.AddPath(location_field_number_for_nested_type); | 919 group_location.AddPath(location_field_number_for_nested_type); |
705 group_location.AddPath(messages->size()); | 920 group_location.AddPath(messages->size()); |
706 | 921 |
707 DescriptorProto* group = messages->Add(); | 922 DescriptorProto* group = messages->Add(); |
708 group->set_name(field->name()); | 923 group->set_name(field->name()); |
709 | 924 |
710 // Record name location to match the field name's location. | 925 // Record name location to match the field name's location. |
711 { | 926 { |
712 LocationRecorder location(group_location, | 927 LocationRecorder location(group_location, |
713 DescriptorProto::kNameFieldNumber); | 928 DescriptorProto::kNameFieldNumber); |
(...skipping 15 matching lines...) Expand all Loading... |
729 // with a capital letter and lower-case the field name. New code should | 944 // with a capital letter and lower-case the field name. New code should |
730 // not use groups; it should use nested messages. | 945 // not use groups; it should use nested messages. |
731 if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { | 946 if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { |
732 AddError(name_token.line, name_token.column, | 947 AddError(name_token.line, name_token.column, |
733 "Group names must start with a capital letter."); | 948 "Group names must start with a capital letter."); |
734 } | 949 } |
735 LowerString(field->mutable_name()); | 950 LowerString(field->mutable_name()); |
736 | 951 |
737 field->set_type_name(group->name()); | 952 field->set_type_name(group->name()); |
738 if (LookingAt("{")) { | 953 if (LookingAt("{")) { |
739 DO(ParseMessageBlock(group, group_location)); | 954 DO(ParseMessageBlock(group, group_location, containing_file)); |
740 } else { | 955 } else { |
741 AddError("Missing group body."); | 956 AddError("Missing group body."); |
742 return false; | 957 return false; |
743 } | 958 } |
744 } else { | 959 } else { |
745 DO(ConsumeEndOfDeclaration(";", &field_location)); | 960 DO(ConsumeEndOfDeclaration(";", &field_location)); |
746 } | 961 } |
747 | 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 |
748 return true; | 968 return true; |
749 } | 969 } |
750 | 970 |
| 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 |
751 bool Parser::ParseFieldOptions(FieldDescriptorProto* field, | 1035 bool Parser::ParseFieldOptions(FieldDescriptorProto* field, |
752 const LocationRecorder& field_location) { | 1036 const LocationRecorder& field_location, |
| 1037 const FileDescriptorProto* containing_file) { |
753 if (!LookingAt("[")) return true; | 1038 if (!LookingAt("[")) return true; |
754 | 1039 |
755 LocationRecorder location(field_location, | 1040 LocationRecorder location(field_location, |
756 FieldDescriptorProto::kOptionsFieldNumber); | 1041 FieldDescriptorProto::kOptionsFieldNumber); |
757 | 1042 |
758 DO(Consume("[")); | 1043 DO(Consume("[")); |
759 | 1044 |
760 // Parse field options. | 1045 // Parse field options. |
761 do { | 1046 do { |
762 if (LookingAt("default")) { | 1047 if (LookingAt("default")) { |
763 // We intentionally pass field_location rather than location here, since | 1048 // We intentionally pass field_location rather than location here, since |
764 // the default value is not actually an option. | 1049 // the default value is not actually an option. |
765 DO(ParseDefaultAssignment(field, field_location)); | 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)); |
766 } else { | 1054 } else { |
767 DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT)); | 1055 DO(ParseOption(field->mutable_options(), location, |
| 1056 containing_file, OPTION_ASSIGNMENT)); |
768 } | 1057 } |
769 } while (TryConsume(",")); | 1058 } while (TryConsume(",")); |
770 | 1059 |
771 DO(Consume("]")); | 1060 DO(Consume("]")); |
772 return true; | 1061 return true; |
773 } | 1062 } |
774 | 1063 |
775 bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, | 1064 bool Parser::ParseDefaultAssignment( |
776 const LocationRecorder& field_location) { | 1065 FieldDescriptorProto* field, |
| 1066 const LocationRecorder& field_location, |
| 1067 const FileDescriptorProto* containing_file) { |
777 if (field->has_default_value()) { | 1068 if (field->has_default_value()) { |
778 AddError("Already set option \"default\"."); | 1069 AddError("Already set option \"default\"."); |
779 field->clear_default_value(); | 1070 field->clear_default_value(); |
780 } | 1071 } |
781 | 1072 |
782 DO(Consume("default")); | 1073 DO(Consume("default")); |
783 DO(Consume("=")); | 1074 DO(Consume("=")); |
784 | 1075 |
785 LocationRecorder location(field_location, | 1076 LocationRecorder location(field_location, |
786 FieldDescriptorProto::kDefaultValueFieldNumber); | 1077 FieldDescriptorProto::kDefaultValueFieldNumber); |
787 location.RecordLegacyLocation( | 1078 location.RecordLegacyLocation( |
788 field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); | 1079 field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); |
789 string* default_value = field->mutable_default_value(); | 1080 string* default_value = field->mutable_default_value(); |
790 | 1081 |
791 if (!field->has_type()) { | 1082 if (!field->has_type()) { |
792 // The field has a type name, but we don't know if it is a message or an | 1083 // The field has a type name, but we don't know if it is a message or an |
793 // enum yet. Assume an enum for now. | 1084 // enum yet. (If it were a primitive type, |field| would have a type set |
794 DO(ConsumeIdentifier(default_value, "Expected identifier.")); | 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(); |
795 return true; | 1094 return true; |
796 } | 1095 } |
797 | 1096 |
798 switch (field->type()) { | 1097 switch (field->type()) { |
799 case FieldDescriptorProto::TYPE_INT32: | 1098 case FieldDescriptorProto::TYPE_INT32: |
800 case FieldDescriptorProto::TYPE_INT64: | 1099 case FieldDescriptorProto::TYPE_INT64: |
801 case FieldDescriptorProto::TYPE_SINT32: | 1100 case FieldDescriptorProto::TYPE_SINT32: |
802 case FieldDescriptorProto::TYPE_SINT64: | 1101 case FieldDescriptorProto::TYPE_SINT64: |
803 case FieldDescriptorProto::TYPE_SFIXED32: | 1102 case FieldDescriptorProto::TYPE_SFIXED32: |
804 case FieldDescriptorProto::TYPE_SFIXED64: { | 1103 case FieldDescriptorProto::TYPE_SFIXED64: { |
805 uint64 max_value = kint64max; | 1104 uint64 max_value = kint64max; |
806 if (field->type() == FieldDescriptorProto::TYPE_INT32 || | 1105 if (field->type() == FieldDescriptorProto::TYPE_INT32 || |
807 field->type() == FieldDescriptorProto::TYPE_SINT32 || | 1106 field->type() == FieldDescriptorProto::TYPE_SINT32 || |
808 field->type() == FieldDescriptorProto::TYPE_SFIXED32) { | 1107 field->type() == FieldDescriptorProto::TYPE_SFIXED32) { |
809 max_value = kint32max; | 1108 max_value = kint32max; |
810 } | 1109 } |
811 | 1110 |
812 // These types can be negative. | 1111 // These types can be negative. |
813 if (TryConsume("-")) { | 1112 if (TryConsume("-")) { |
814 default_value->append("-"); | 1113 default_value->append("-"); |
815 // Two's complement always has one more negative value than positive. | 1114 // Two's complement always has one more negative value than positive. |
816 ++max_value; | 1115 ++max_value; |
817 } | 1116 } |
818 // Parse the integer to verify that it is not out-of-range. | 1117 // Parse the integer to verify that it is not out-of-range. |
819 uint64 value; | 1118 uint64 value; |
820 DO(ConsumeInteger64(max_value, &value, "Expected integer.")); | 1119 DO(ConsumeInteger64(max_value, &value, |
| 1120 "Expected integer for field default value.")); |
821 // And stringify it again. | 1121 // And stringify it again. |
822 default_value->append(SimpleItoa(value)); | 1122 default_value->append(SimpleItoa(value)); |
823 break; | 1123 break; |
824 } | 1124 } |
825 | 1125 |
826 case FieldDescriptorProto::TYPE_UINT32: | 1126 case FieldDescriptorProto::TYPE_UINT32: |
827 case FieldDescriptorProto::TYPE_UINT64: | 1127 case FieldDescriptorProto::TYPE_UINT64: |
828 case FieldDescriptorProto::TYPE_FIXED32: | 1128 case FieldDescriptorProto::TYPE_FIXED32: |
829 case FieldDescriptorProto::TYPE_FIXED64: { | 1129 case FieldDescriptorProto::TYPE_FIXED64: { |
830 uint64 max_value = kuint64max; | 1130 uint64 max_value = kuint64max; |
831 if (field->type() == FieldDescriptorProto::TYPE_UINT32 || | 1131 if (field->type() == FieldDescriptorProto::TYPE_UINT32 || |
832 field->type() == FieldDescriptorProto::TYPE_FIXED32) { | 1132 field->type() == FieldDescriptorProto::TYPE_FIXED32) { |
833 max_value = kuint32max; | 1133 max_value = kuint32max; |
834 } | 1134 } |
835 | 1135 |
836 // Numeric, not negative. | 1136 // Numeric, not negative. |
837 if (TryConsume("-")) { | 1137 if (TryConsume("-")) { |
838 AddError("Unsigned field can't have negative default value."); | 1138 AddError("Unsigned field can't have negative default value."); |
839 } | 1139 } |
840 // Parse the integer to verify that it is not out-of-range. | 1140 // Parse the integer to verify that it is not out-of-range. |
841 uint64 value; | 1141 uint64 value; |
842 DO(ConsumeInteger64(max_value, &value, "Expected integer.")); | 1142 DO(ConsumeInteger64(max_value, &value, |
| 1143 "Expected integer for field default value.")); |
843 // And stringify it again. | 1144 // And stringify it again. |
844 default_value->append(SimpleItoa(value)); | 1145 default_value->append(SimpleItoa(value)); |
845 break; | 1146 break; |
846 } | 1147 } |
847 | 1148 |
848 case FieldDescriptorProto::TYPE_FLOAT: | 1149 case FieldDescriptorProto::TYPE_FLOAT: |
849 case FieldDescriptorProto::TYPE_DOUBLE: | 1150 case FieldDescriptorProto::TYPE_DOUBLE: |
850 // These types can be negative. | 1151 // These types can be negative. |
851 if (TryConsume("-")) { | 1152 if (TryConsume("-")) { |
852 default_value->append("-"); | 1153 default_value->append("-"); |
(...skipping 11 matching lines...) Expand all Loading... |
864 default_value->assign("true"); | 1165 default_value->assign("true"); |
865 } else if (TryConsume("false")) { | 1166 } else if (TryConsume("false")) { |
866 default_value->assign("false"); | 1167 default_value->assign("false"); |
867 } else { | 1168 } else { |
868 AddError("Expected \"true\" or \"false\"."); | 1169 AddError("Expected \"true\" or \"false\"."); |
869 return false; | 1170 return false; |
870 } | 1171 } |
871 break; | 1172 break; |
872 | 1173 |
873 case FieldDescriptorProto::TYPE_STRING: | 1174 case FieldDescriptorProto::TYPE_STRING: |
874 DO(ConsumeString(default_value, "Expected 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.")); |
875 break; | 1180 break; |
876 | 1181 |
877 case FieldDescriptorProto::TYPE_BYTES: | 1182 case FieldDescriptorProto::TYPE_BYTES: |
878 DO(ConsumeString(default_value, "Expected string.")); | 1183 DO(ConsumeString(default_value, "Expected string.")); |
879 *default_value = CEscape(*default_value); | 1184 *default_value = CEscape(*default_value); |
880 break; | 1185 break; |
881 | 1186 |
882 case FieldDescriptorProto::TYPE_ENUM: | 1187 case FieldDescriptorProto::TYPE_ENUM: |
883 DO(ConsumeIdentifier(default_value, "Expected identifier.")); | 1188 DO(ConsumeIdentifier(default_value, "Expected enum identifier for field " |
| 1189 "default value.")); |
884 break; | 1190 break; |
885 | 1191 |
886 case FieldDescriptorProto::TYPE_MESSAGE: | 1192 case FieldDescriptorProto::TYPE_MESSAGE: |
887 case FieldDescriptorProto::TYPE_GROUP: | 1193 case FieldDescriptorProto::TYPE_GROUP: |
888 AddError("Messages can't have default values."); | 1194 AddError("Messages can't have default values."); |
889 return false; | 1195 return false; |
890 } | 1196 } |
891 | 1197 |
892 return true; | 1198 return true; |
893 } | 1199 } |
894 | 1200 |
| 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 |
895 bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, | 1223 bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, |
896 const LocationRecorder& part_location) { | 1224 const LocationRecorder& part_location, |
| 1225 const FileDescriptorProto* containing_file) { |
897 UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); | 1226 UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); |
898 string identifier; // We parse identifiers into this string. | 1227 string identifier; // We parse identifiers into this string. |
899 if (LookingAt("(")) { // This is an extension. | 1228 if (LookingAt("(")) { // This is an extension. |
900 DO(Consume("(")); | 1229 DO(Consume("(")); |
901 | 1230 |
902 { | 1231 { |
903 LocationRecorder location( | 1232 LocationRecorder location( |
904 part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); | 1233 part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); |
905 // An extension name consists of dot-separated identifiers, and may begin | 1234 // An extension name consists of dot-separated identifiers, and may begin |
906 // with a dot. | 1235 // with a dot. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 input_->Next(); | 1279 input_->Next(); |
951 } | 1280 } |
952 AddError("Unexpected end of stream while parsing aggregate value."); | 1281 AddError("Unexpected end of stream while parsing aggregate value."); |
953 return false; | 1282 return false; |
954 } | 1283 } |
955 | 1284 |
956 // We don't interpret the option here. Instead we store it in an | 1285 // We don't interpret the option here. Instead we store it in an |
957 // UninterpretedOption, to be interpreted later. | 1286 // UninterpretedOption, to be interpreted later. |
958 bool Parser::ParseOption(Message* options, | 1287 bool Parser::ParseOption(Message* options, |
959 const LocationRecorder& options_location, | 1288 const LocationRecorder& options_location, |
| 1289 const FileDescriptorProto* containing_file, |
960 OptionStyle style) { | 1290 OptionStyle style) { |
961 // Create an entry in the uninterpreted_option field. | 1291 // Create an entry in the uninterpreted_option field. |
962 const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> | 1292 const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> |
963 FindFieldByName("uninterpreted_option"); | 1293 FindFieldByName("uninterpreted_option"); |
964 GOOGLE_CHECK(uninterpreted_option_field != NULL) | 1294 GOOGLE_CHECK(uninterpreted_option_field != NULL) |
965 << "No field named \"uninterpreted_option\" in the Options proto."; | 1295 << "No field named \"uninterpreted_option\" in the Options proto."; |
966 | 1296 |
967 const Reflection* reflection = options->GetReflection(); | 1297 const Reflection* reflection = options->GetReflection(); |
968 | 1298 |
969 LocationRecorder location( | 1299 LocationRecorder location( |
(...skipping 11 matching lines...) Expand all Loading... |
981 // Parse dot-separated name. | 1311 // Parse dot-separated name. |
982 { | 1312 { |
983 LocationRecorder name_location(location, | 1313 LocationRecorder name_location(location, |
984 UninterpretedOption::kNameFieldNumber); | 1314 UninterpretedOption::kNameFieldNumber); |
985 name_location.RecordLegacyLocation( | 1315 name_location.RecordLegacyLocation( |
986 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); | 1316 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); |
987 | 1317 |
988 { | 1318 { |
989 LocationRecorder part_location(name_location, | 1319 LocationRecorder part_location(name_location, |
990 uninterpreted_option->name_size()); | 1320 uninterpreted_option->name_size()); |
991 DO(ParseOptionNamePart(uninterpreted_option, part_location)); | 1321 DO(ParseOptionNamePart(uninterpreted_option, part_location, |
| 1322 containing_file)); |
992 } | 1323 } |
993 | 1324 |
994 while (LookingAt(".")) { | 1325 while (LookingAt(".")) { |
995 DO(Consume(".")); | 1326 DO(Consume(".")); |
996 LocationRecorder part_location(name_location, | 1327 LocationRecorder part_location(name_location, |
997 uninterpreted_option->name_size()); | 1328 uninterpreted_option->name_size()); |
998 DO(ParseOptionNamePart(uninterpreted_option, part_location)); | 1329 DO(ParseOptionNamePart(uninterpreted_option, part_location, |
| 1330 containing_file)); |
999 } | 1331 } |
1000 } | 1332 } |
1001 | 1333 |
1002 DO(Consume("=")); | 1334 DO(Consume("=")); |
1003 | 1335 |
1004 { | 1336 { |
1005 LocationRecorder value_location(location); | 1337 LocationRecorder value_location(location); |
1006 value_location.RecordLegacyLocation( | 1338 value_location.RecordLegacyLocation( |
1007 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); | 1339 uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); |
1008 | 1340 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 } | 1417 } |
1086 | 1418 |
1087 if (style == OPTION_STATEMENT) { | 1419 if (style == OPTION_STATEMENT) { |
1088 DO(ConsumeEndOfDeclaration(";", &location)); | 1420 DO(ConsumeEndOfDeclaration(";", &location)); |
1089 } | 1421 } |
1090 | 1422 |
1091 return true; | 1423 return true; |
1092 } | 1424 } |
1093 | 1425 |
1094 bool Parser::ParseExtensions(DescriptorProto* message, | 1426 bool Parser::ParseExtensions(DescriptorProto* message, |
1095 const LocationRecorder& extensions_location) { | 1427 const LocationRecorder& extensions_location, |
| 1428 const FileDescriptorProto* containing_file) { |
1096 // Parse the declaration. | 1429 // Parse the declaration. |
1097 DO(Consume("extensions")); | 1430 DO(Consume("extensions")); |
1098 | 1431 |
1099 do { | 1432 do { |
1100 // Note that kExtensionRangeFieldNumber was already pushed by the parent. | 1433 // Note that kExtensionRangeFieldNumber was already pushed by the parent. |
1101 LocationRecorder location(extensions_location, | 1434 LocationRecorder location(extensions_location, |
1102 message->extension_range_size()); | 1435 message->extension_range_size()); |
1103 | 1436 |
1104 DescriptorProto::ExtensionRange* range = message->add_extension_range(); | 1437 DescriptorProto::ExtensionRange* range = message->add_extension_range(); |
1105 location.RecordLegacyLocation( | 1438 location.RecordLegacyLocation( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 ++end; | 1472 ++end; |
1140 | 1473 |
1141 range->set_start(start); | 1474 range->set_start(start); |
1142 range->set_end(end); | 1475 range->set_end(end); |
1143 } while (TryConsume(",")); | 1476 } while (TryConsume(",")); |
1144 | 1477 |
1145 DO(ConsumeEndOfDeclaration(";", &extensions_location)); | 1478 DO(ConsumeEndOfDeclaration(";", &extensions_location)); |
1146 return true; | 1479 return true; |
1147 } | 1480 } |
1148 | 1481 |
| 1482 // This is similar to extension range parsing, except that "max" is not |
| 1483 // supported, and accepts field name literals. |
| 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 |
| 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 |
| 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 |
1149 bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, | 1553 bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, |
1150 RepeatedPtrField<DescriptorProto>* messages, | 1554 RepeatedPtrField<DescriptorProto>* messages, |
1151 const LocationRecorder& parent_location, | 1555 const LocationRecorder& parent_location, |
1152 int location_field_number_for_nested_type, | 1556 int location_field_number_for_nested_type, |
1153 const LocationRecorder& extend_location) { | 1557 const LocationRecorder& extend_location, |
| 1558 const FileDescriptorProto* containing_file) { |
1154 DO(Consume("extend")); | 1559 DO(Consume("extend")); |
1155 | 1560 |
1156 // Parse the extendee type. | 1561 // Parse the extendee type. |
1157 io::Tokenizer::Token extendee_start = input_->current(); | 1562 io::Tokenizer::Token extendee_start = input_->current(); |
1158 string extendee; | 1563 string extendee; |
1159 DO(ParseUserDefinedType(&extendee)); | 1564 DO(ParseUserDefinedType(&extendee)); |
1160 io::Tokenizer::Token extendee_end = input_->previous(); | 1565 io::Tokenizer::Token extendee_end = input_->previous(); |
1161 | 1566 |
1162 // Parse the block. | 1567 // Parse the block. |
1163 DO(ConsumeEndOfDeclaration("{", &extend_location)); | 1568 DO(ConsumeEndOfDeclaration("{", &extend_location)); |
(...skipping 21 matching lines...) Expand all Loading... |
1185 extendee_location.RecordLegacyLocation( | 1590 extendee_location.RecordLegacyLocation( |
1186 field, DescriptorPool::ErrorCollector::EXTENDEE); | 1591 field, DescriptorPool::ErrorCollector::EXTENDEE); |
1187 is_first = false; | 1592 is_first = false; |
1188 } | 1593 } |
1189 } | 1594 } |
1190 | 1595 |
1191 field->set_extendee(extendee); | 1596 field->set_extendee(extendee); |
1192 | 1597 |
1193 if (!ParseMessageField(field, messages, parent_location, | 1598 if (!ParseMessageField(field, messages, parent_location, |
1194 location_field_number_for_nested_type, | 1599 location_field_number_for_nested_type, |
1195 location)) { | 1600 location, |
| 1601 containing_file)) { |
1196 // This statement failed to parse. Skip it, but keep looping to parse | 1602 // This statement failed to parse. Skip it, but keep looping to parse |
1197 // other statements. | 1603 // other statements. |
1198 SkipStatement(); | 1604 SkipStatement(); |
| 1605 } |
| 1606 } while (!TryConsumeEndOfDeclaration("}", NULL)); |
| 1607 |
| 1608 return true; |
| 1609 } |
| 1610 |
| 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 // Print a nice error if the user accidentally tries to place a label |
| 1634 // on an individual member of a oneof. |
| 1635 if (LookingAt("required") || |
| 1636 LookingAt("optional") || |
| 1637 LookingAt("repeated")) { |
| 1638 AddError("Fields in oneofs must not have labels (required / optional " |
| 1639 "/ repeated)."); |
| 1640 // We can continue parsing here because we understand what the user |
| 1641 // meant. The error report will still make parsing fail overall. |
| 1642 input_->Next(); |
| 1643 } |
| 1644 |
| 1645 LocationRecorder field_location(containing_type_location, |
| 1646 DescriptorProto::kFieldFieldNumber, |
| 1647 containing_type->field_size()); |
| 1648 |
| 1649 FieldDescriptorProto* field = containing_type->add_field(); |
| 1650 field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); |
| 1651 field->set_oneof_index(oneof_index); |
| 1652 |
| 1653 if (!ParseMessageFieldNoLabel(field, |
| 1654 containing_type->mutable_nested_type(), |
| 1655 containing_type_location, |
| 1656 DescriptorProto::kNestedTypeFieldNumber, |
| 1657 field_location, |
| 1658 containing_file)) { |
| 1659 // This statement failed to parse. Skip it, but keep looping to parse |
| 1660 // other statements. |
| 1661 SkipStatement(); |
1199 } | 1662 } |
1200 } while (!TryConsumeEndOfDeclaration("}", NULL)); | 1663 } while (!TryConsumeEndOfDeclaration("}", NULL)); |
1201 | 1664 |
1202 return true; | 1665 return true; |
1203 } | 1666 } |
1204 | 1667 |
1205 // ------------------------------------------------------------------- | 1668 // ------------------------------------------------------------------- |
1206 // Enums | 1669 // Enums |
1207 | 1670 |
1208 bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, | 1671 bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, |
1209 const LocationRecorder& enum_location) { | 1672 const LocationRecorder& enum_location, |
| 1673 const FileDescriptorProto* containing_file) { |
1210 DO(Consume("enum")); | 1674 DO(Consume("enum")); |
1211 | 1675 |
1212 { | 1676 { |
1213 LocationRecorder location(enum_location, | 1677 LocationRecorder location(enum_location, |
1214 EnumDescriptorProto::kNameFieldNumber); | 1678 EnumDescriptorProto::kNameFieldNumber); |
1215 location.RecordLegacyLocation( | 1679 location.RecordLegacyLocation( |
1216 enum_type, DescriptorPool::ErrorCollector::NAME); | 1680 enum_type, DescriptorPool::ErrorCollector::NAME); |
1217 DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); | 1681 DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); |
1218 } | 1682 } |
1219 | 1683 |
1220 DO(ParseEnumBlock(enum_type, enum_location)); | 1684 DO(ParseEnumBlock(enum_type, enum_location, containing_file)); |
| 1685 |
| 1686 DO(ValidateEnum(enum_type)); |
| 1687 |
1221 return true; | 1688 return true; |
1222 } | 1689 } |
1223 | 1690 |
1224 bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, | 1691 bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, |
1225 const LocationRecorder& enum_location) { | 1692 const LocationRecorder& enum_location, |
| 1693 const FileDescriptorProto* containing_file) { |
1226 DO(ConsumeEndOfDeclaration("{", &enum_location)); | 1694 DO(ConsumeEndOfDeclaration("{", &enum_location)); |
1227 | 1695 |
1228 while (!TryConsumeEndOfDeclaration("}", NULL)) { | 1696 while (!TryConsumeEndOfDeclaration("}", NULL)) { |
1229 if (AtEnd()) { | 1697 if (AtEnd()) { |
1230 AddError("Reached end of input in enum definition (missing '}')."); | 1698 AddError("Reached end of input in enum definition (missing '}')."); |
1231 return false; | 1699 return false; |
1232 } | 1700 } |
1233 | 1701 |
1234 if (!ParseEnumStatement(enum_type, enum_location)) { | 1702 if (!ParseEnumStatement(enum_type, enum_location, containing_file)) { |
1235 // This statement failed to parse. Skip it, but keep looping to parse | 1703 // This statement failed to parse. Skip it, but keep looping to parse |
1236 // other statements. | 1704 // other statements. |
1237 SkipStatement(); | 1705 SkipStatement(); |
1238 } | 1706 } |
1239 } | 1707 } |
1240 | 1708 |
1241 return true; | 1709 return true; |
1242 } | 1710 } |
1243 | 1711 |
1244 bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, | 1712 bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, |
1245 const LocationRecorder& enum_location) { | 1713 const LocationRecorder& enum_location, |
| 1714 const FileDescriptorProto* containing_file) { |
1246 if (TryConsumeEndOfDeclaration(";", NULL)) { | 1715 if (TryConsumeEndOfDeclaration(";", NULL)) { |
1247 // empty statement; ignore | 1716 // empty statement; ignore |
1248 return true; | 1717 return true; |
1249 } else if (LookingAt("option")) { | 1718 } else if (LookingAt("option")) { |
1250 LocationRecorder location(enum_location, | 1719 LocationRecorder location(enum_location, |
1251 EnumDescriptorProto::kOptionsFieldNumber); | 1720 EnumDescriptorProto::kOptionsFieldNumber); |
1252 return ParseOption(enum_type->mutable_options(), location, | 1721 return ParseOption(enum_type->mutable_options(), location, |
1253 OPTION_STATEMENT); | 1722 containing_file, OPTION_STATEMENT); |
1254 } else { | 1723 } else { |
1255 LocationRecorder location(enum_location, | 1724 LocationRecorder location(enum_location, |
1256 EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); | 1725 EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); |
1257 return ParseEnumConstant(enum_type->add_value(), location); | 1726 return ParseEnumConstant(enum_type->add_value(), location, containing_file); |
1258 } | 1727 } |
1259 } | 1728 } |
1260 | 1729 |
1261 bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, | 1730 bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, |
1262 const LocationRecorder& enum_value_location) { | 1731 const LocationRecorder& enum_value_location, |
| 1732 const FileDescriptorProto* containing_file) { |
1263 // Parse name. | 1733 // Parse name. |
1264 { | 1734 { |
1265 LocationRecorder location(enum_value_location, | 1735 LocationRecorder location(enum_value_location, |
1266 EnumValueDescriptorProto::kNameFieldNumber); | 1736 EnumValueDescriptorProto::kNameFieldNumber); |
1267 location.RecordLegacyLocation( | 1737 location.RecordLegacyLocation( |
1268 enum_value, DescriptorPool::ErrorCollector::NAME); | 1738 enum_value, DescriptorPool::ErrorCollector::NAME); |
1269 DO(ConsumeIdentifier(enum_value->mutable_name(), | 1739 DO(ConsumeIdentifier(enum_value->mutable_name(), |
1270 "Expected enum constant name.")); | 1740 "Expected enum constant name.")); |
1271 } | 1741 } |
1272 | 1742 |
1273 DO(Consume("=", "Missing numeric value for enum constant.")); | 1743 DO(Consume("=", "Missing numeric value for enum constant.")); |
1274 | 1744 |
1275 // Parse value. | 1745 // Parse value. |
1276 { | 1746 { |
1277 LocationRecorder location( | 1747 LocationRecorder location( |
1278 enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); | 1748 enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); |
1279 location.RecordLegacyLocation( | 1749 location.RecordLegacyLocation( |
1280 enum_value, DescriptorPool::ErrorCollector::NUMBER); | 1750 enum_value, DescriptorPool::ErrorCollector::NUMBER); |
1281 | 1751 |
1282 int number; | 1752 int number; |
1283 DO(ConsumeSignedInteger(&number, "Expected integer.")); | 1753 DO(ConsumeSignedInteger(&number, "Expected integer.")); |
1284 enum_value->set_number(number); | 1754 enum_value->set_number(number); |
1285 } | 1755 } |
1286 | 1756 |
1287 DO(ParseEnumConstantOptions(enum_value, enum_value_location)); | 1757 DO(ParseEnumConstantOptions(enum_value, enum_value_location, |
| 1758 containing_file)); |
1288 | 1759 |
1289 DO(ConsumeEndOfDeclaration(";", &enum_value_location)); | 1760 DO(ConsumeEndOfDeclaration(";", &enum_value_location)); |
1290 | 1761 |
1291 return true; | 1762 return true; |
1292 } | 1763 } |
1293 | 1764 |
1294 bool Parser::ParseEnumConstantOptions( | 1765 bool Parser::ParseEnumConstantOptions( |
1295 EnumValueDescriptorProto* value, | 1766 EnumValueDescriptorProto* value, |
1296 const LocationRecorder& enum_value_location) { | 1767 const LocationRecorder& enum_value_location, |
| 1768 const FileDescriptorProto* containing_file) { |
1297 if (!LookingAt("[")) return true; | 1769 if (!LookingAt("[")) return true; |
1298 | 1770 |
1299 LocationRecorder location( | 1771 LocationRecorder location( |
1300 enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); | 1772 enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); |
1301 | 1773 |
1302 DO(Consume("[")); | 1774 DO(Consume("[")); |
1303 | 1775 |
1304 do { | 1776 do { |
1305 DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT)); | 1777 DO(ParseOption(value->mutable_options(), location, |
| 1778 containing_file, OPTION_ASSIGNMENT)); |
1306 } while (TryConsume(",")); | 1779 } while (TryConsume(",")); |
1307 | 1780 |
1308 DO(Consume("]")); | 1781 DO(Consume("]")); |
1309 return true; | 1782 return true; |
1310 } | 1783 } |
1311 | 1784 |
1312 // ------------------------------------------------------------------- | 1785 // ------------------------------------------------------------------- |
1313 // Services | 1786 // Services |
1314 | 1787 |
1315 bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service, | 1788 bool Parser::ParseServiceDefinition( |
1316 const LocationRecorder& service_location) { | 1789 ServiceDescriptorProto* service, |
| 1790 const LocationRecorder& service_location, |
| 1791 const FileDescriptorProto* containing_file) { |
1317 DO(Consume("service")); | 1792 DO(Consume("service")); |
1318 | 1793 |
1319 { | 1794 { |
1320 LocationRecorder location(service_location, | 1795 LocationRecorder location(service_location, |
1321 ServiceDescriptorProto::kNameFieldNumber); | 1796 ServiceDescriptorProto::kNameFieldNumber); |
1322 location.RecordLegacyLocation( | 1797 location.RecordLegacyLocation( |
1323 service, DescriptorPool::ErrorCollector::NAME); | 1798 service, DescriptorPool::ErrorCollector::NAME); |
1324 DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); | 1799 DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); |
1325 } | 1800 } |
1326 | 1801 |
1327 DO(ParseServiceBlock(service, service_location)); | 1802 DO(ParseServiceBlock(service, service_location, containing_file)); |
1328 return true; | 1803 return true; |
1329 } | 1804 } |
1330 | 1805 |
1331 bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, | 1806 bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, |
1332 const LocationRecorder& service_location) { | 1807 const LocationRecorder& service_location, |
| 1808 const FileDescriptorProto* containing_file) { |
1333 DO(ConsumeEndOfDeclaration("{", &service_location)); | 1809 DO(ConsumeEndOfDeclaration("{", &service_location)); |
1334 | 1810 |
1335 while (!TryConsumeEndOfDeclaration("}", NULL)) { | 1811 while (!TryConsumeEndOfDeclaration("}", NULL)) { |
1336 if (AtEnd()) { | 1812 if (AtEnd()) { |
1337 AddError("Reached end of input in service definition (missing '}')."); | 1813 AddError("Reached end of input in service definition (missing '}')."); |
1338 return false; | 1814 return false; |
1339 } | 1815 } |
1340 | 1816 |
1341 if (!ParseServiceStatement(service, service_location)) { | 1817 if (!ParseServiceStatement(service, service_location, containing_file)) { |
1342 // This statement failed to parse. Skip it, but keep looping to parse | 1818 // This statement failed to parse. Skip it, but keep looping to parse |
1343 // other statements. | 1819 // other statements. |
1344 SkipStatement(); | 1820 SkipStatement(); |
1345 } | 1821 } |
1346 } | 1822 } |
1347 | 1823 |
1348 return true; | 1824 return true; |
1349 } | 1825 } |
1350 | 1826 |
1351 bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, | 1827 bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, |
1352 const LocationRecorder& service_location) { | 1828 const LocationRecorder& service_location, |
| 1829 const FileDescriptorProto* containing_file) { |
1353 if (TryConsumeEndOfDeclaration(";", NULL)) { | 1830 if (TryConsumeEndOfDeclaration(";", NULL)) { |
1354 // empty statement; ignore | 1831 // empty statement; ignore |
1355 return true; | 1832 return true; |
1356 } else if (LookingAt("option")) { | 1833 } else if (LookingAt("option")) { |
1357 LocationRecorder location( | 1834 LocationRecorder location( |
1358 service_location, ServiceDescriptorProto::kOptionsFieldNumber); | 1835 service_location, ServiceDescriptorProto::kOptionsFieldNumber); |
1359 return ParseOption(service->mutable_options(), location, OPTION_STATEMENT); | 1836 return ParseOption(service->mutable_options(), location, |
| 1837 containing_file, OPTION_STATEMENT); |
1360 } else { | 1838 } else { |
1361 LocationRecorder location(service_location, | 1839 LocationRecorder location(service_location, |
1362 ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); | 1840 ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); |
1363 return ParseServiceMethod(service->add_method(), location); | 1841 return ParseServiceMethod(service->add_method(), location, containing_file); |
1364 } | 1842 } |
1365 } | 1843 } |
1366 | 1844 |
1367 bool Parser::ParseServiceMethod(MethodDescriptorProto* method, | 1845 bool Parser::ParseServiceMethod(MethodDescriptorProto* method, |
1368 const LocationRecorder& method_location) { | 1846 const LocationRecorder& method_location, |
| 1847 const FileDescriptorProto* containing_file) { |
1369 DO(Consume("rpc")); | 1848 DO(Consume("rpc")); |
1370 | 1849 |
1371 { | 1850 { |
1372 LocationRecorder location(method_location, | 1851 LocationRecorder location(method_location, |
1373 MethodDescriptorProto::kNameFieldNumber); | 1852 MethodDescriptorProto::kNameFieldNumber); |
1374 location.RecordLegacyLocation( | 1853 location.RecordLegacyLocation( |
1375 method, DescriptorPool::ErrorCollector::NAME); | 1854 method, DescriptorPool::ErrorCollector::NAME); |
1376 DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); | 1855 DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); |
1377 } | 1856 } |
1378 | 1857 |
1379 // Parse input type. | 1858 // Parse input type. |
1380 DO(Consume("(")); | 1859 DO(Consume("(")); |
1381 { | 1860 { |
| 1861 if (LookingAt("stream")) { |
| 1862 LocationRecorder location( |
| 1863 method_location, MethodDescriptorProto::kClientStreamingFieldNumber); |
| 1864 location.RecordLegacyLocation( |
| 1865 method, DescriptorPool::ErrorCollector::OTHER); |
| 1866 method->set_client_streaming(true); |
| 1867 DO(Consume("stream")); |
| 1868 |
| 1869 } |
1382 LocationRecorder location(method_location, | 1870 LocationRecorder location(method_location, |
1383 MethodDescriptorProto::kInputTypeFieldNumber); | 1871 MethodDescriptorProto::kInputTypeFieldNumber); |
1384 location.RecordLegacyLocation( | 1872 location.RecordLegacyLocation( |
1385 method, DescriptorPool::ErrorCollector::INPUT_TYPE); | 1873 method, DescriptorPool::ErrorCollector::INPUT_TYPE); |
1386 DO(ParseUserDefinedType(method->mutable_input_type())); | 1874 DO(ParseUserDefinedType(method->mutable_input_type())); |
1387 } | 1875 } |
1388 DO(Consume(")")); | 1876 DO(Consume(")")); |
1389 | 1877 |
1390 // Parse output type. | 1878 // Parse output type. |
1391 DO(Consume("returns")); | 1879 DO(Consume("returns")); |
1392 DO(Consume("(")); | 1880 DO(Consume("(")); |
1393 { | 1881 { |
| 1882 if (LookingAt("stream")) { |
| 1883 LocationRecorder location( |
| 1884 method_location, MethodDescriptorProto::kServerStreamingFieldNumber); |
| 1885 location.RecordLegacyLocation( |
| 1886 method, DescriptorPool::ErrorCollector::OTHER); |
| 1887 DO(Consume("stream")); |
| 1888 method->set_server_streaming(true); |
| 1889 |
| 1890 } |
1394 LocationRecorder location(method_location, | 1891 LocationRecorder location(method_location, |
1395 MethodDescriptorProto::kOutputTypeFieldNumber); | 1892 MethodDescriptorProto::kOutputTypeFieldNumber); |
1396 location.RecordLegacyLocation( | 1893 location.RecordLegacyLocation( |
1397 method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); | 1894 method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); |
1398 DO(ParseUserDefinedType(method->mutable_output_type())); | 1895 DO(ParseUserDefinedType(method->mutable_output_type())); |
1399 } | 1896 } |
1400 DO(Consume(")")); | 1897 DO(Consume(")")); |
1401 | 1898 |
1402 if (LookingAt("{")) { | 1899 if (LookingAt("{")) { |
1403 // Options! | 1900 // Options! |
1404 DO(ParseOptions(method_location, | 1901 DO(ParseMethodOptions(method_location, containing_file, |
1405 MethodDescriptorProto::kOptionsFieldNumber, | 1902 MethodDescriptorProto::kOptionsFieldNumber, |
1406 method->mutable_options())); | 1903 method->mutable_options())); |
1407 } else { | 1904 } else { |
1408 DO(ConsumeEndOfDeclaration(";", &method_location)); | 1905 DO(ConsumeEndOfDeclaration(";", &method_location)); |
1409 } | 1906 } |
1410 | 1907 |
1411 return true; | 1908 return true; |
1412 } | 1909 } |
1413 | 1910 |
1414 | 1911 |
1415 bool Parser::ParseOptions(const LocationRecorder& parent_location, | 1912 bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, |
1416 const int optionsFieldNumber, | 1913 const FileDescriptorProto* containing_file, |
1417 Message* mutable_options) { | 1914 const int optionsFieldNumber, |
| 1915 Message* mutable_options) { |
1418 // Options! | 1916 // Options! |
1419 ConsumeEndOfDeclaration("{", &parent_location); | 1917 ConsumeEndOfDeclaration("{", &parent_location); |
1420 while (!TryConsumeEndOfDeclaration("}", NULL)) { | 1918 while (!TryConsumeEndOfDeclaration("}", NULL)) { |
1421 if (AtEnd()) { | 1919 if (AtEnd()) { |
1422 AddError("Reached end of input in method options (missing '}')."); | 1920 AddError("Reached end of input in method options (missing '}')."); |
1423 return false; | 1921 return false; |
1424 } | 1922 } |
1425 | 1923 |
1426 if (TryConsumeEndOfDeclaration(";", NULL)) { | 1924 if (TryConsumeEndOfDeclaration(";", NULL)) { |
1427 // empty statement; ignore | 1925 // empty statement; ignore |
1428 } else { | 1926 } else { |
1429 LocationRecorder location(parent_location, | 1927 LocationRecorder location(parent_location, |
1430 optionsFieldNumber); | 1928 optionsFieldNumber); |
1431 if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) { | 1929 if (!ParseOption(mutable_options, location, |
| 1930 containing_file, OPTION_STATEMENT)) { |
1432 // This statement failed to parse. Skip it, but keep looping to | 1931 // This statement failed to parse. Skip it, but keep looping to |
1433 // parse other statements. | 1932 // parse other statements. |
1434 SkipStatement(); | 1933 SkipStatement(); |
1435 } | 1934 } |
1436 } | 1935 } |
1437 } | 1936 } |
1438 | 1937 |
1439 return true; | 1938 return true; |
1440 } | 1939 } |
1441 | 1940 |
1442 // ------------------------------------------------------------------- | 1941 // ------------------------------------------------------------------- |
1443 | 1942 |
1444 bool Parser::ParseLabel(FieldDescriptorProto::Label* label) { | 1943 bool Parser::ParseLabel(FieldDescriptorProto::Label* label, |
| 1944 const FileDescriptorProto* containing_file) { |
1445 if (TryConsume("optional")) { | 1945 if (TryConsume("optional")) { |
1446 *label = FieldDescriptorProto::LABEL_OPTIONAL; | 1946 *label = FieldDescriptorProto::LABEL_OPTIONAL; |
1447 return true; | 1947 return true; |
1448 } else if (TryConsume("repeated")) { | 1948 } else if (TryConsume("repeated")) { |
1449 *label = FieldDescriptorProto::LABEL_REPEATED; | 1949 *label = FieldDescriptorProto::LABEL_REPEATED; |
1450 return true; | 1950 return true; |
1451 } else if (TryConsume("required")) { | 1951 } else if (TryConsume("required")) { |
1452 *label = FieldDescriptorProto::LABEL_REQUIRED; | 1952 *label = FieldDescriptorProto::LABEL_REQUIRED; |
1453 return true; | 1953 return true; |
1454 } else { | |
1455 AddError("Expected \"required\", \"optional\", or \"repeated\"."); | |
1456 // We can actually reasonably recover here by just assuming the user | |
1457 // forgot the label altogether. | |
1458 *label = FieldDescriptorProto::LABEL_OPTIONAL; | |
1459 return true; | |
1460 } | 1954 } |
| 1955 return false; |
1461 } | 1956 } |
1462 | 1957 |
1463 bool Parser::ParseType(FieldDescriptorProto::Type* type, | 1958 bool Parser::ParseType(FieldDescriptorProto::Type* type, |
1464 string* type_name) { | 1959 string* type_name) { |
1465 TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); | 1960 TypeNameMap::const_iterator iter = kTypeNames.find(input_->current().text); |
1466 if (iter != kTypeNames.end()) { | 1961 if (iter != kTypeNames.end()) { |
1467 *type = iter->second; | 1962 *type = iter->second; |
1468 input_->Next(); | 1963 input_->Next(); |
1469 } else { | 1964 } else { |
1470 DO(ParseUserDefinedType(type_name)); | 1965 DO(ParseUserDefinedType(type_name)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 DO(ConsumeIdentifier(&identifier, "Expected identifier.")); | 1998 DO(ConsumeIdentifier(&identifier, "Expected identifier.")); |
1504 type_name->append(identifier); | 1999 type_name->append(identifier); |
1505 } | 2000 } |
1506 | 2001 |
1507 return true; | 2002 return true; |
1508 } | 2003 } |
1509 | 2004 |
1510 // =================================================================== | 2005 // =================================================================== |
1511 | 2006 |
1512 bool Parser::ParsePackage(FileDescriptorProto* file, | 2007 bool Parser::ParsePackage(FileDescriptorProto* file, |
1513 const LocationRecorder& root_location) { | 2008 const LocationRecorder& root_location, |
| 2009 const FileDescriptorProto* containing_file) { |
1514 if (file->has_package()) { | 2010 if (file->has_package()) { |
1515 AddError("Multiple package definitions."); | 2011 AddError("Multiple package definitions."); |
1516 // Don't append the new package to the old one. Just replace it. Not | 2012 // Don't append the new package to the old one. Just replace it. Not |
1517 // that it really matters since this is an error anyway. | 2013 // that it really matters since this is an error anyway. |
1518 file->clear_package(); | 2014 file->clear_package(); |
1519 } | 2015 } |
1520 | 2016 |
1521 DO(Consume("package")); | 2017 DO(Consume("package")); |
1522 | 2018 |
1523 { | 2019 { |
(...skipping 13 matching lines...) Expand all Loading... |
1537 | 2033 |
1538 DO(ConsumeEndOfDeclaration(";", &location)); | 2034 DO(ConsumeEndOfDeclaration(";", &location)); |
1539 } | 2035 } |
1540 | 2036 |
1541 return true; | 2037 return true; |
1542 } | 2038 } |
1543 | 2039 |
1544 bool Parser::ParseImport(RepeatedPtrField<string>* dependency, | 2040 bool Parser::ParseImport(RepeatedPtrField<string>* dependency, |
1545 RepeatedField<int32>* public_dependency, | 2041 RepeatedField<int32>* public_dependency, |
1546 RepeatedField<int32>* weak_dependency, | 2042 RepeatedField<int32>* weak_dependency, |
1547 const LocationRecorder& root_location) { | 2043 const LocationRecorder& root_location, |
| 2044 const FileDescriptorProto* containing_file) { |
1548 DO(Consume("import")); | 2045 DO(Consume("import")); |
1549 if (LookingAt("public")) { | 2046 if (LookingAt("public")) { |
1550 LocationRecorder location( | 2047 LocationRecorder location( |
1551 root_location, FileDescriptorProto::kPublicDependencyFieldNumber, | 2048 root_location, FileDescriptorProto::kPublicDependencyFieldNumber, |
1552 public_dependency->size()); | 2049 public_dependency->size()); |
1553 DO(Consume("public")); | 2050 DO(Consume("public")); |
1554 *public_dependency->Add() = dependency->size(); | 2051 *public_dependency->Add() = dependency->size(); |
1555 } else if (LookingAt("weak")) { | 2052 } else if (LookingAt("weak")) { |
1556 LocationRecorder location( | 2053 LocationRecorder location( |
1557 root_location, FileDescriptorProto::kWeakDependencyFieldNumber, | 2054 root_location, FileDescriptorProto::kWeakDependencyFieldNumber, |
(...skipping 18 matching lines...) Expand all Loading... |
1576 // =================================================================== | 2073 // =================================================================== |
1577 | 2074 |
1578 SourceLocationTable::SourceLocationTable() {} | 2075 SourceLocationTable::SourceLocationTable() {} |
1579 SourceLocationTable::~SourceLocationTable() {} | 2076 SourceLocationTable::~SourceLocationTable() {} |
1580 | 2077 |
1581 bool SourceLocationTable::Find( | 2078 bool SourceLocationTable::Find( |
1582 const Message* descriptor, | 2079 const Message* descriptor, |
1583 DescriptorPool::ErrorCollector::ErrorLocation location, | 2080 DescriptorPool::ErrorCollector::ErrorLocation location, |
1584 int* line, int* column) const { | 2081 int* line, int* column) const { |
1585 const pair<int, int>* result = | 2082 const pair<int, int>* result = |
1586 FindOrNull(location_map_, make_pair(descriptor, location)); | 2083 FindOrNull(location_map_, std::make_pair(descriptor, location)); |
1587 if (result == NULL) { | 2084 if (result == NULL) { |
1588 *line = -1; | 2085 *line = -1; |
1589 *column = 0; | 2086 *column = 0; |
1590 return false; | 2087 return false; |
1591 } else { | 2088 } else { |
1592 *line = result->first; | 2089 *line = result->first; |
1593 *column = result->second; | 2090 *column = result->second; |
1594 return true; | 2091 return true; |
1595 } | 2092 } |
1596 } | 2093 } |
1597 | 2094 |
1598 void SourceLocationTable::Add( | 2095 void SourceLocationTable::Add( |
1599 const Message* descriptor, | 2096 const Message* descriptor, |
1600 DescriptorPool::ErrorCollector::ErrorLocation location, | 2097 DescriptorPool::ErrorCollector::ErrorLocation location, |
1601 int line, int column) { | 2098 int line, int column) { |
1602 location_map_[make_pair(descriptor, location)] = make_pair(line, column); | 2099 location_map_[std::make_pair(descriptor, location)] = |
| 2100 std::make_pair(line, column); |
1603 } | 2101 } |
1604 | 2102 |
1605 void SourceLocationTable::Clear() { | 2103 void SourceLocationTable::Clear() { |
1606 location_map_.clear(); | 2104 location_map_.clear(); |
1607 } | 2105 } |
1608 | 2106 |
1609 } // namespace compiler | 2107 } // namespace compiler |
1610 } // namespace protobuf | 2108 } // namespace protobuf |
1611 } // namespace google | 2109 } // namespace google |
OLD | NEW |