| 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 |