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