| 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 | |