• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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