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