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