1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 // Author: kenton@google.com (Kenton Varda) 32 // Based on original Protocol Buffers design by 33 // Sanjay Ghemawat, Jeff Dean, and others. 34 // 35 // Implements parsing of .proto files to FileDescriptorProtos. 36 37 #ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__ 38 #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__ 39 40 #include <map> 41 #include <string> 42 #include <utility> 43 #include <google/protobuf/descriptor.pb.h> 44 #include <google/protobuf/io/tokenizer.h> 45 #include <google/protobuf/descriptor.h> 46 #include <google/protobuf/repeated_field.h> 47 48 #include <google/protobuf/port_def.inc> 49 50 namespace google { 51 namespace protobuf { 52 53 class Message; 54 55 namespace compiler { 56 57 // Defined in this file. 58 class Parser; 59 class SourceLocationTable; 60 61 // Implements parsing of protocol definitions (such as .proto files). 62 // 63 // Note that most users will be more interested in the Importer class. 64 // Parser is a lower-level class which simply converts a single .proto file 65 // to a FileDescriptorProto. It does not resolve import directives or perform 66 // many other kinds of validation needed to construct a complete 67 // FileDescriptor. 68 class PROTOBUF_EXPORT Parser { 69 public: 70 Parser(); 71 ~Parser(); 72 73 // Parse the entire input and construct a FileDescriptorProto representing 74 // it. Returns true if no errors occurred, false otherwise. 75 bool Parse(io::Tokenizer* input, FileDescriptorProto* file); 76 77 // Optional features: 78 79 // DEPRECATED: New code should use the SourceCodeInfo embedded in the 80 // FileDescriptorProto. 81 // 82 // Requests that locations of certain definitions be recorded to the given 83 // SourceLocationTable while parsing. This can be used to look up exact line 84 // and column numbers for errors reported by DescriptorPool during validation. 85 // Set to NULL (the default) to discard source location information. RecordSourceLocationsTo(SourceLocationTable * location_table)86 void RecordSourceLocationsTo(SourceLocationTable* location_table) { 87 source_location_table_ = location_table; 88 } 89 90 // Requests that errors be recorded to the given ErrorCollector while 91 // parsing. Set to NULL (the default) to discard error messages. RecordErrorsTo(io::ErrorCollector * error_collector)92 void RecordErrorsTo(io::ErrorCollector* error_collector) { 93 error_collector_ = error_collector; 94 } 95 96 // Returns the identifier used in the "syntax = " declaration, if one was 97 // seen during the last call to Parse(), or the empty string otherwise. GetSyntaxIdentifier()98 const std::string& GetSyntaxIdentifier() { return syntax_identifier_; } 99 100 // If set true, input files will be required to begin with a syntax 101 // identifier. Otherwise, files may omit this. If a syntax identifier 102 // is provided, it must be 'syntax = "proto2";' and must appear at the 103 // top of this file regardless of whether or not it was required. SetRequireSyntaxIdentifier(bool value)104 void SetRequireSyntaxIdentifier(bool value) { 105 require_syntax_identifier_ = value; 106 } 107 108 // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop 109 // parsing as soon as it has seen the syntax identifier, or lack thereof. 110 // This is useful for quickly identifying the syntax of the file without 111 // parsing the whole thing. If this is enabled, no error will be recorded 112 // if the syntax identifier is something other than "proto2" (since 113 // presumably the caller intends to deal with that), but other kinds of 114 // errors (e.g. parse errors) will still be reported. When this is enabled, 115 // you may pass a NULL FileDescriptorProto to Parse(). SetStopAfterSyntaxIdentifier(bool value)116 void SetStopAfterSyntaxIdentifier(bool value) { 117 stop_after_syntax_identifier_ = value; 118 } 119 120 private: 121 class LocationRecorder; 122 123 // ================================================================= 124 // Error recovery helpers 125 126 // Consume the rest of the current statement. This consumes tokens 127 // until it sees one of: 128 // ';' Consumes the token and returns. 129 // '{' Consumes the brace then calls SkipRestOfBlock(). 130 // '}' Returns without consuming. 131 // EOF Returns (can't consume). 132 // The Parser often calls SkipStatement() after encountering a syntax 133 // error. This allows it to go on parsing the following lines, allowing 134 // it to report more than just one error in the file. 135 void SkipStatement(); 136 137 // Consume the rest of the current block, including nested blocks, 138 // ending after the closing '}' is encountered and consumed, or at EOF. 139 void SkipRestOfBlock(); 140 141 // ----------------------------------------------------------------- 142 // Single-token consuming helpers 143 // 144 // These make parsing code more readable. 145 146 // True if the current token is TYPE_END. 147 inline bool AtEnd(); 148 149 // True if the next token matches the given text. 150 inline bool LookingAt(const char* text); 151 // True if the next token is of the given type. 152 inline bool LookingAtType(io::Tokenizer::TokenType token_type); 153 154 // If the next token exactly matches the text given, consume it and return 155 // true. Otherwise, return false without logging an error. 156 bool TryConsume(const char* text); 157 158 // These attempt to read some kind of token from the input. If successful, 159 // they return true. Otherwise they return false and add the given error 160 // to the error list. 161 162 // Consume a token with the exact text given. 163 bool Consume(const char* text, const char* error); 164 // Same as above, but automatically generates the error "Expected \"text\".", 165 // where "text" is the expected token text. 166 bool Consume(const char* text); 167 // Consume a token of type IDENTIFIER and store its text in "output". 168 bool ConsumeIdentifier(std::string* output, const char* error); 169 // Consume an integer and store its value in "output". 170 bool ConsumeInteger(int* output, const char* error); 171 // Consume a signed integer and store its value in "output". 172 bool ConsumeSignedInteger(int* output, const char* error); 173 // Consume a 64-bit integer and store its value in "output". If the value 174 // is greater than max_value, an error will be reported. 175 bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error); 176 // Consume a number and store its value in "output". This will accept 177 // tokens of either INTEGER or FLOAT type. 178 bool ConsumeNumber(double* output, const char* error); 179 // Consume a string literal and store its (unescaped) value in "output". 180 bool ConsumeString(std::string* output, const char* error); 181 182 // Consume a token representing the end of the statement. Comments between 183 // this token and the next will be harvested for documentation. The given 184 // LocationRecorder should refer to the declaration that was just parsed; 185 // it will be populated with these comments. 186 // 187 // TODO(kenton): The LocationRecorder is const because historically locations 188 // have been passed around by const reference, for no particularly good 189 // reason. We should probably go through and change them all to mutable 190 // pointer to make this more intuitive. 191 bool TryConsumeEndOfDeclaration(const char* text, 192 const LocationRecorder* location); 193 bool TryConsumeEndOfDeclarationFinishScope(const char* text, 194 const LocationRecorder* location); 195 196 bool ConsumeEndOfDeclaration(const char* text, 197 const LocationRecorder* location); 198 199 // ----------------------------------------------------------------- 200 // Error logging helpers 201 202 // Invokes error_collector_->AddError(), if error_collector_ is not NULL. 203 void AddError(int line, int column, const std::string& error); 204 205 // Invokes error_collector_->AddError() with the line and column number 206 // of the current token. 207 void AddError(const std::string& error); 208 209 // Invokes error_collector_->AddWarning() with the line and column number 210 // of the current token. 211 void AddWarning(const string& warning); 212 213 // Records a location in the SourceCodeInfo.location table (see 214 // descriptor.proto). We use RAII to ensure that the start and end locations 215 // are recorded -- the constructor records the start location and the 216 // destructor records the end location. Since the parser is 217 // recursive-descent, this works out beautifully. 218 class PROTOBUF_EXPORT LocationRecorder { 219 public: 220 // Construct the file's "root" location. 221 LocationRecorder(Parser* parser); 222 223 // Construct a location that represents a declaration nested within the 224 // given parent. E.g. a field's location is nested within the location 225 // for a message type. The parent's path will be copied, so you should 226 // call AddPath() only to add the path components leading from the parent 227 // to the child (as opposed to leading from the root to the child). 228 LocationRecorder(const LocationRecorder& parent); 229 230 // Convenience constructors that call AddPath() one or two times. 231 LocationRecorder(const LocationRecorder& parent, int path1); 232 LocationRecorder(const LocationRecorder& parent, int path1, int path2); 233 234 // Creates a recorder that generates locations into given source code info. 235 LocationRecorder(const LocationRecorder& parent, int path1, 236 SourceCodeInfo* source_code_info); 237 238 ~LocationRecorder(); 239 240 // Add a path component. See SourceCodeInfo.Location.path in 241 // descriptor.proto. 242 void AddPath(int path_component); 243 244 // By default the location is considered to start at the current token at 245 // the time the LocationRecorder is created. StartAt() sets the start 246 // location to the given token instead. 247 void StartAt(const io::Tokenizer::Token& token); 248 249 // Start at the same location as some other LocationRecorder. 250 void StartAt(const LocationRecorder& other); 251 252 // By default the location is considered to end at the previous token at 253 // the time the LocationRecorder is destroyed. EndAt() sets the end 254 // location to the given token instead. 255 void EndAt(const io::Tokenizer::Token& token); 256 257 // Records the start point of this location to the SourceLocationTable that 258 // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable 259 // is an older way of keeping track of source locations which is still 260 // used in some places. 261 void RecordLegacyLocation( 262 const Message* descriptor, 263 DescriptorPool::ErrorCollector::ErrorLocation location); 264 void RecordLegacyImportLocation(const Message* descriptor, 265 const string& name); 266 267 // Returns the number of path components in the recorder's current location. 268 int CurrentPathSize() const; 269 270 // Attaches leading and trailing comments to the location. The two strings 271 // will be swapped into place, so after this is called *leading and 272 // *trailing will be empty. 273 // 274 // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for 275 // why this is const. 276 void AttachComments(std::string* leading, std::string* trailing, 277 std::vector<std::string>* detached_comments) const; 278 279 private: 280 // Indexes of parent and current location in the parent 281 // SourceCodeInfo.location repeated field. For top-level elements, 282 // parent_index_ is -1. 283 Parser* parser_; 284 SourceCodeInfo* source_code_info_; 285 SourceCodeInfo::Location* location_; 286 287 void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info); 288 }; 289 290 // ================================================================= 291 // Parsers for various language constructs 292 293 // Parses the "syntax = \"proto2\";" line at the top of the file. Returns 294 // false if it failed to parse or if the syntax identifier was not 295 // recognized. 296 bool ParseSyntaxIdentifier(const LocationRecorder& parent); 297 298 // These methods parse various individual bits of code. They return 299 // false if they completely fail to parse the construct. In this case, 300 // it is probably necessary to skip the rest of the statement to recover. 301 // However, if these methods return true, it does NOT mean that there 302 // were no errors; only that there were no *syntax* errors. For instance, 303 // if a service method is defined using proper syntax but uses a primitive 304 // type as its input or output, ParseMethodField() still returns true 305 // and only reports the error by calling AddError(). In practice, this 306 // makes logic much simpler for the caller. 307 308 // Parse a top-level message, enum, service, etc. 309 bool ParseTopLevelStatement(FileDescriptorProto* file, 310 const LocationRecorder& root_location); 311 312 // Parse various language high-level language construrcts. 313 bool ParseMessageDefinition(DescriptorProto* message, 314 const LocationRecorder& message_location, 315 const FileDescriptorProto* containing_file); 316 bool ParseEnumDefinition(EnumDescriptorProto* enum_type, 317 const LocationRecorder& enum_location, 318 const FileDescriptorProto* containing_file); 319 bool ParseServiceDefinition(ServiceDescriptorProto* service, 320 const LocationRecorder& service_location, 321 const FileDescriptorProto* containing_file); 322 bool ParsePackage(FileDescriptorProto* file, 323 const LocationRecorder& root_location, 324 const FileDescriptorProto* containing_file); 325 bool ParseImport(RepeatedPtrField<std::string>* dependency, 326 RepeatedField<int32>* public_dependency, 327 RepeatedField<int32>* weak_dependency, 328 const LocationRecorder& root_location, 329 const FileDescriptorProto* containing_file); 330 331 // These methods parse the contents of a message, enum, or service type and 332 // add them to the given object. They consume the entire block including 333 // the beginning and ending brace. 334 bool ParseMessageBlock(DescriptorProto* message, 335 const LocationRecorder& message_location, 336 const FileDescriptorProto* containing_file); 337 bool ParseEnumBlock(EnumDescriptorProto* enum_type, 338 const LocationRecorder& enum_location, 339 const FileDescriptorProto* containing_file); 340 bool ParseServiceBlock(ServiceDescriptorProto* service, 341 const LocationRecorder& service_location, 342 const FileDescriptorProto* containing_file); 343 344 // Parse one statement within a message, enum, or service block, including 345 // final semicolon. 346 bool ParseMessageStatement(DescriptorProto* message, 347 const LocationRecorder& message_location, 348 const FileDescriptorProto* containing_file); 349 bool ParseEnumStatement(EnumDescriptorProto* message, 350 const LocationRecorder& enum_location, 351 const FileDescriptorProto* containing_file); 352 bool ParseServiceStatement(ServiceDescriptorProto* message, 353 const LocationRecorder& service_location, 354 const FileDescriptorProto* containing_file); 355 356 // Parse a field of a message. If the field is a group, its type will be 357 // added to "messages". 358 // 359 // parent_location and location_field_number_for_nested_type are needed when 360 // parsing groups -- we need to generate a nested message type within the 361 // parent and record its location accordingly. Since the parent could be 362 // either a FileDescriptorProto or a DescriptorProto, we must pass in the 363 // correct field number to use. 364 bool ParseMessageField(FieldDescriptorProto* field, 365 RepeatedPtrField<DescriptorProto>* messages, 366 const LocationRecorder& parent_location, 367 int location_field_number_for_nested_type, 368 const LocationRecorder& field_location, 369 const FileDescriptorProto* containing_file); 370 371 // Like ParseMessageField() but expects the label has already been filled in 372 // by the caller. 373 bool ParseMessageFieldNoLabel(FieldDescriptorProto* field, 374 RepeatedPtrField<DescriptorProto>* messages, 375 const LocationRecorder& parent_location, 376 int location_field_number_for_nested_type, 377 const LocationRecorder& field_location, 378 const FileDescriptorProto* containing_file); 379 380 // Parse an "extensions" declaration. 381 bool ParseExtensions(DescriptorProto* message, 382 const LocationRecorder& extensions_location, 383 const FileDescriptorProto* containing_file); 384 385 // Parse a "reserved" declaration. 386 bool ParseReserved(DescriptorProto* message, 387 const LocationRecorder& message_location); 388 bool ParseReservedNames(DescriptorProto* message, 389 const LocationRecorder& parent_location); 390 bool ParseReservedNumbers(DescriptorProto* message, 391 const LocationRecorder& parent_location); 392 bool ParseReserved(EnumDescriptorProto* message, 393 const LocationRecorder& message_location); 394 bool ParseReservedNames(EnumDescriptorProto* message, 395 const LocationRecorder& parent_location); 396 bool ParseReservedNumbers(EnumDescriptorProto* message, 397 const LocationRecorder& parent_location); 398 399 // Parse an "extend" declaration. (See also comments for 400 // ParseMessageField().) 401 bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, 402 RepeatedPtrField<DescriptorProto>* messages, 403 const LocationRecorder& parent_location, 404 int location_field_number_for_nested_type, 405 const LocationRecorder& extend_location, 406 const FileDescriptorProto* containing_file); 407 408 // Parse a "oneof" declaration. The caller is responsible for setting 409 // oneof_decl->label() since it will have had to parse the label before it 410 // knew it was parsing a oneof. 411 bool ParseOneof(OneofDescriptorProto* oneof_decl, 412 DescriptorProto* containing_type, int oneof_index, 413 const LocationRecorder& oneof_location, 414 const LocationRecorder& containing_type_location, 415 const FileDescriptorProto* containing_file); 416 417 // Parse a single enum value within an enum block. 418 bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, 419 const LocationRecorder& enum_value_location, 420 const FileDescriptorProto* containing_file); 421 422 // Parse enum constant options, i.e. the list in square brackets at the end 423 // of the enum constant value definition. 424 bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, 425 const LocationRecorder& enum_value_location, 426 const FileDescriptorProto* containing_file); 427 428 // Parse a single method within a service definition. 429 bool ParseServiceMethod(MethodDescriptorProto* method, 430 const LocationRecorder& method_location, 431 const FileDescriptorProto* containing_file); 432 433 434 // Parse options of a single method or stream. 435 bool ParseMethodOptions(const LocationRecorder& parent_location, 436 const FileDescriptorProto* containing_file, 437 const int optionsFieldNumber, 438 Message* mutable_options); 439 440 // Parse "required", "optional", or "repeated" and fill in "label" 441 // with the value. Returns true if such a label is consumed. 442 bool ParseLabel(FieldDescriptorProto::Label* label, 443 const FileDescriptorProto* containing_file); 444 445 // Parse a type name and fill in "type" (if it is a primitive) or 446 // "type_name" (if it is not) with the type parsed. 447 bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name); 448 // Parse a user-defined type and fill in "type_name" with the name. 449 // If a primitive type is named, it is treated as an error. 450 bool ParseUserDefinedType(std::string* type_name); 451 452 // Parses field options, i.e. the stuff in square brackets at the end 453 // of a field definition. Also parses default value. 454 bool ParseFieldOptions(FieldDescriptorProto* field, 455 const LocationRecorder& field_location, 456 const FileDescriptorProto* containing_file); 457 458 // Parse the "default" option. This needs special handling because its 459 // type is the field's type. 460 bool ParseDefaultAssignment(FieldDescriptorProto* field, 461 const LocationRecorder& field_location, 462 const FileDescriptorProto* containing_file); 463 464 bool ParseJsonName(FieldDescriptorProto* field, 465 const LocationRecorder& field_location, 466 const FileDescriptorProto* containing_file); 467 468 enum OptionStyle { 469 OPTION_ASSIGNMENT, // just "name = value" 470 OPTION_STATEMENT // "option name = value;" 471 }; 472 473 // Parse a single option name/value pair, e.g. "ctype = CORD". The name 474 // identifies a field of the given Message, and the value of that field 475 // is set to the parsed value. 476 bool ParseOption(Message* options, const LocationRecorder& options_location, 477 const FileDescriptorProto* containing_file, 478 OptionStyle style); 479 480 // Parses a single part of a multipart option name. A multipart name consists 481 // of names separated by dots. Each name is either an identifier or a series 482 // of identifiers separated by dots and enclosed in parentheses. E.g., 483 // "foo.(bar.baz).qux". 484 bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, 485 const LocationRecorder& part_location, 486 const FileDescriptorProto* containing_file); 487 488 // Parses a string surrounded by balanced braces. Strips off the outer 489 // braces and stores the enclosed string in *value. 490 // E.g., 491 // { foo } *value gets 'foo' 492 // { foo { bar: box } } *value gets 'foo { bar: box }' 493 // {} *value gets '' 494 // 495 // REQUIRES: LookingAt("{") 496 // When finished successfully, we are looking at the first token past 497 // the ending brace. 498 bool ParseUninterpretedBlock(std::string* value); 499 500 struct MapField { 501 // Whether the field is a map field. 502 bool is_map_field; 503 // The types of the key and value if they are primitive types. 504 FieldDescriptorProto::Type key_type; 505 FieldDescriptorProto::Type value_type; 506 // Or the type names string if the types are customized types. 507 std::string key_type_name; 508 std::string value_type_name; 509 MapFieldMapField510 MapField() : is_map_field(false) {} 511 }; 512 // Desugar the map syntax to generate a nested map entry message. 513 void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field, 514 RepeatedPtrField<DescriptorProto>* messages); 515 516 // Whether fields without label default to optional fields. DefaultToOptionalFields()517 bool DefaultToOptionalFields() const { 518 return syntax_identifier_ == "proto3"; 519 } 520 521 522 bool ValidateEnum(const EnumDescriptorProto* proto); 523 524 // ================================================================= 525 526 io::Tokenizer* input_; 527 io::ErrorCollector* error_collector_; 528 SourceCodeInfo* source_code_info_; 529 SourceLocationTable* source_location_table_; // legacy 530 bool had_errors_; 531 bool require_syntax_identifier_; 532 bool stop_after_syntax_identifier_; 533 std::string syntax_identifier_; 534 535 // Leading doc comments for the next declaration. These are not complete 536 // yet; use ConsumeEndOfDeclaration() to get the complete comments. 537 std::string upcoming_doc_comments_; 538 539 // Detached comments are not connected to any syntax entities. Elements in 540 // this vector are paragraphs of comments separated by empty lines. The 541 // detached comments will be put into the leading_detached_comments field for 542 // the next element (See SourceCodeInfo.Location in descriptor.proto), when 543 // ConsumeEndOfDeclaration() is called. 544 std::vector<std::string> upcoming_detached_comments_; 545 546 GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); 547 }; 548 549 // A table mapping (descriptor, ErrorLocation) pairs -- as reported by 550 // DescriptorPool when validating descriptors -- to line and column numbers 551 // within the original source code. 552 // 553 // This is semi-obsolete: FileDescriptorProto.source_code_info now contains 554 // far more complete information about source locations. However, as of this 555 // writing you still need to use SourceLocationTable when integrating with 556 // DescriptorPool. 557 class PROTOBUF_EXPORT SourceLocationTable { 558 public: 559 SourceLocationTable(); 560 ~SourceLocationTable(); 561 562 // Finds the precise location of the given error and fills in *line and 563 // *column with the line and column numbers. If not found, sets *line to 564 // -1 and *column to 0 (since line = -1 is used to mean "error has no exact 565 // location" in the ErrorCollector interface). Returns true if found, false 566 // otherwise. 567 bool Find(const Message* descriptor, 568 DescriptorPool::ErrorCollector::ErrorLocation location, int* line, 569 int* column) const; 570 bool FindImport(const Message* descriptor, const string& name, int* line, 571 int* column) const; 572 573 // Adds a location to the table. 574 void Add(const Message* descriptor, 575 DescriptorPool::ErrorCollector::ErrorLocation location, int line, 576 int column); 577 void AddImport(const Message* descriptor, const string& name, int line, 578 int column); 579 580 // Clears the contents of the table. 581 void Clear(); 582 583 private: 584 typedef std::map< 585 std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>, 586 std::pair<int, int> > 587 LocationMap; 588 LocationMap location_map_; 589 std::map<std::pair<const Message*, string>, std::pair<int, int> > 590 import_location_map_; 591 }; 592 593 } // namespace compiler 594 } // namespace protobuf 595 } // namespace google 596 597 #include <google/protobuf/port_undef.inc> 598 599 #endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__ 600