15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Protocol Buffers - Google's data interchange format
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2008 Google Inc.  All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/protobuf/
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: kenton@google.com (Kenton Varda)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Based on original Protocol Buffers design by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Sanjay Ghemawat, Jeff Dean, and others.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements parsing of .proto files to FileDescriptorProtos.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/stubs/common.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.h>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/descriptor.pb.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/repeated_field.h>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <google/protobuf/io/tokenizer.h>
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace google {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf { class Message; }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace protobuf {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace compiler {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Defined in this file.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Parser;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SourceLocationTable;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements parsing of protocol definitions (such as .proto files).
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that most users will be more interested in the Importer class.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Parser is a lower-level class which simply converts a single .proto file
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a FileDescriptorProto.  It does not resolve import directives or perform
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// many other kinds of validation needed to construct a complete
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FileDescriptor.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LIBPROTOBUF_EXPORT Parser {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parser();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Parser();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the entire input and construct a FileDescriptorProto representing
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it.  Returns true if no errors occurred, false otherwise.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Optional fetaures:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   FileDescriptorProto.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requests that locations of certain definitions be recorded to the given
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SourceLocationTable while parsing.  This can be used to look up exact line
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and column numbers for errors reported by DescriptorPool during validation.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set to NULL (the default) to discard source location information.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordSourceLocationsTo(SourceLocationTable* location_table) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    source_location_table_ = location_table;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Requests that errors be recorded to the given ErrorCollector while
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parsing.  Set to NULL (the default) to discard error messages.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RecordErrorsTo(io::ErrorCollector* error_collector) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_collector_ = error_collector;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the identifier used in the "syntax = " declaration, if one was
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // seen during the last call to Parse(), or the empty string otherwise.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string& GetSyntaxIdentifier() { return syntax_identifier_; }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If set true, input files will be required to begin with a syntax
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // identifier.  Otherwise, files may omit this.  If a syntax identifier
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is provided, it must be 'syntax = "proto2";' and must appear at the
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // top of this file regardless of whether or not it was required.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetRequireSyntaxIdentifier(bool value) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    require_syntax_identifier_ = value;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parsing as soon as it has seen the syntax identifier, or lack thereof.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is useful for quickly identifying the syntax of the file without
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parsing the whole thing.  If this is enabled, no error will be recorded
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if the syntax identifier is something other than "proto2" (since
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // presumably the caller intends to deal with that), but other kinds of
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // errors (e.g. parse errors) will still be reported.  When this is enabled,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // you may pass a NULL FileDescriptorProto to Parse().
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetStopAfterSyntaxIdentifier(bool value) {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stop_after_syntax_identifier_ = value;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  class LocationRecorder;
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // =================================================================
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Error recovery helpers
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume the rest of the current statement.  This consumes tokens
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until it sees one of:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ';'  Consumes the token and returns.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   '{'  Consumes the brace then calls SkipRestOfBlock().
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   '}'  Returns without consuming.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   EOF  Returns (can't consume).
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Parser often calls SkipStatement() after encountering a syntax
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // error.  This allows it to go on parsing the following lines, allowing
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it to report more than just one error in the file.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SkipStatement();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume the rest of the current block, including nested blocks,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ending after the closing '}' is encountered and consumed, or at EOF.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SkipRestOfBlock();
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Single-token consuming helpers
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These make parsing code more readable.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the current token is TYPE_END.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool AtEnd();
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the next token matches the given text.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool LookingAt(const char* text);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // True if the next token is of the given type.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool LookingAtType(io::Tokenizer::TokenType token_type);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the next token exactly matches the text given, consume it and return
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true.  Otherwise, return false without logging an error.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TryConsume(const char* text);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These attempt to read some kind of token from the input.  If successful,
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // they return true.  Otherwise they return false and add the given error
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the error list.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume a token with the exact text given.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Consume(const char* text, const char* error);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same as above, but automatically generates the error "Expected \"text\".",
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // where "text" is the expected token text.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Consume(const char* text);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume a token of type IDENTIFIER and store its text in "output".
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeIdentifier(string* output, const char* error);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume an integer and store its value in "output".
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeInteger(int* output, const char* error);
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Consume a signed integer and store its value in "output".
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool ConsumeSignedInteger(int* output, const char* error);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume a 64-bit integer and store its value in "output".  If the value
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is greater than max_value, an error will be reported.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume a number and store its value in "output".  This will accept
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // tokens of either INTEGER or FLOAT type.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeNumber(double* output, const char* error);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Consume a string literal and store its (unescaped) value in "output".
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ConsumeString(string* output, const char* error);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Consume a token representing the end of the statement.  Comments between
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // this token and the next will be harvested for documentation.  The given
182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // LocationRecorder should refer to the declaration that was just parsed;
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // it will be populated with these comments.
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // TODO(kenton):  The LocationRecorder is const because historically locations
186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //   have been passed around by const reference, for no particularly good
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //   reason.  We should probably go through and change them all to mutable
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  //   pointer to make this more intuitive.
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool TryConsumeEndOfDeclaration(const char* text,
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                  const LocationRecorder* location);
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool ConsumeEndOfDeclaration(const char* text,
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                               const LocationRecorder* location);
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -----------------------------------------------------------------
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Error logging helpers
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes error_collector_->AddError(), if error_collector_ is not NULL.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddError(int line, int column, const string& error);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invokes error_collector_->AddError() with the line and column number
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the current token.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddError(const string& error);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Records a location in the SourceCodeInfo.location table (see
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptor.proto).  We use RAII to ensure that the start and end locations
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are recorded -- the constructor records the start location and the
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // destructor records the end location.  Since the parser is
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recursive-descent, this works out beautifully.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class LIBPROTOBUF_EXPORT LocationRecorder {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct the file's "root" location.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocationRecorder(Parser* parser);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct a location that represents a declaration nested within the
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // given parent.  E.g. a field's location is nested within the location
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for a message type.  The parent's path will be copied, so you should
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call AddPath() only to add the path components leading from the parent
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to the child (as opposed to leading from the root to the child).
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocationRecorder(const LocationRecorder& parent);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Convenience constructors that call AddPath() one or two times.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocationRecorder(const LocationRecorder& parent, int path1);
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LocationRecorder(const LocationRecorder& parent, int path1, int path2);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~LocationRecorder();
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add a path component.  See SourceCodeInfo.Location.path in
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // descriptor.proto.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddPath(int path_component);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // By default the location is considered to start at the current token at
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the time the LocationRecorder is created.  StartAt() sets the start
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // location to the given token instead.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void StartAt(const io::Tokenizer::Token& token);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // By default the location is considered to end at the previous token at
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the time the LocationRecorder is destroyed.  EndAt() sets the end
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // location to the given token instead.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void EndAt(const io::Tokenizer::Token& token);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Records the start point of this location to the SourceLocationTable that
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // was passed to RecordSourceLocationsTo(), if any.  SourceLocationTable
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is an older way of keeping track of source locations which is still
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // used in some places.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void RecordLegacyLocation(const Message* descriptor,
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DescriptorPool::ErrorCollector::ErrorLocation location);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Attaches leading and trailing comments to the location.  The two strings
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // will be swapped into place, so after this is called *leading and
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // *trailing will be empty.
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // TODO(kenton):  See comment on TryConsumeEndOfDeclaration(), above, for
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    //   why this is const.
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    void AttachComments(string* leading, string* trailing) const;
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Parser* parser_;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SourceCodeInfo::Location* location_;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void Init(const LocationRecorder& parent);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // =================================================================
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parsers for various language constructs
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parses the "syntax = \"proto2\";" line at the top of the file.  Returns
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // false if it failed to parse or if the syntax identifier was not
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // recognized.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseSyntaxIdentifier();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These methods parse various individual bits of code.  They return
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // false if they completely fail to parse the construct.  In this case,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it is probably necessary to skip the rest of the statement to recover.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // However, if these methods return true, it does NOT mean that there
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // were no errors; only that there were no *syntax* errors.  For instance,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if a service method is defined using proper syntax but uses a primitive
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // type as its input or output, ParseMethodField() still returns true
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and only reports the error by calling AddError().  In practice, this
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // makes logic much simpler for the caller.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a top-level message, enum, service, etc.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseTopLevelStatement(FileDescriptorProto* file,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const LocationRecorder& root_location);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse various language high-level language construrcts.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseMessageDefinition(DescriptorProto* message,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const LocationRecorder& message_location);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const LocationRecorder& enum_location);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseServiceDefinition(ServiceDescriptorProto* service,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const LocationRecorder& service_location);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParsePackage(FileDescriptorProto* file,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const LocationRecorder& root_location);
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool ParseImport(RepeatedPtrField<string>* dependency,
295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   RepeatedField<int32>* public_dependency,
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   RepeatedField<int32>* weak_dependency,
297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const LocationRecorder& root_location);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseOption(Message* options,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const LocationRecorder& options_location);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These methods parse the contents of a message, enum, or service type and
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // add them to the given object.  They consume the entire block including
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the beginning and ending brace.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseMessageBlock(DescriptorProto* message,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& message_location);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseEnumBlock(EnumDescriptorProto* enum_type,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const LocationRecorder& enum_location);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseServiceBlock(ServiceDescriptorProto* service,
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& service_location);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse one statement within a message, enum, or service block, inclunding
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // final semicolon.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseMessageStatement(DescriptorProto* message,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const LocationRecorder& message_location);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseEnumStatement(EnumDescriptorProto* message,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const LocationRecorder& enum_location);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseServiceStatement(ServiceDescriptorProto* message,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const LocationRecorder& service_location);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a field of a message.  If the field is a group, its type will be
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // added to "messages".
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parent_location and location_field_number_for_nested_type are needed when
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parsing groups -- we need to generate a nested message type within the
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parent and record its location accordingly.  Since the parent could be
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either a FileDescriptorProto or a DescriptorProto, we must pass in the
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // correct field number to use.
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseMessageField(FieldDescriptorProto* field,
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         RepeatedPtrField<DescriptorProto>* messages,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& parent_location,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int location_field_number_for_nested_type,
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& field_location);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse an "extensions" declaration.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseExtensions(DescriptorProto* message,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const LocationRecorder& extensions_location);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse an "extend" declaration.  (See also comments for
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ParseMessageField().)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   RepeatedPtrField<DescriptorProto>* messages,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const LocationRecorder& parent_location,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   int location_field_number_for_nested_type,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   const LocationRecorder& extend_location);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a single enum value within an enum block.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& enum_value_location);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse enum constant options, i.e. the list in square brackets at the end
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the enum constant value definition.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const LocationRecorder& enum_value_location);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a single method within a service definition.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseServiceMethod(MethodDescriptorProto* method,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const LocationRecorder& method_location);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Parse options of a single method or stream.
361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool ParseOptions(const LocationRecorder& parent_location,
362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    const int optionsFieldNumber,
363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                    Message* mutable_options);
364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse "required", "optional", or "repeated" and fill in "label"
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the value.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseLabel(FieldDescriptorProto::Label* label);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a type name and fill in "type" (if it is a primitive) or
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "type_name" (if it is not) with the type parsed.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseType(FieldDescriptorProto::Type* type,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 string* type_name);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a user-defined type and fill in "type_name" with the name.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If a primitive type is named, it is treated as an error.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseUserDefinedType(string* type_name);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parses field options, i.e. the stuff in square brackets at the end
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of a field definition.  Also parses default value.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseFieldOptions(FieldDescriptorProto* field,
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const LocationRecorder& field_location);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the "default" option.  This needs special handling because its
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // type is the field's type.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseDefaultAssignment(FieldDescriptorProto* field,
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const LocationRecorder& field_location);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
387ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  enum OptionStyle {
388ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OPTION_ASSIGNMENT,  // just "name = value"
389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    OPTION_STATEMENT    // "option name = value;"
390ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  };
391ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // identifies a field of the given Message, and the value of that field
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is set to the parsed value.
395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool ParseOption(Message* options,
396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   const LocationRecorder& options_location,
397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   OptionStyle style);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parses a single part of a multipart option name. A multipart name consists
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of names separated by dots. Each name is either an identifier or a series
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of identifiers separated by dots and enclosed in parentheses. E.g.,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "foo.(bar.baz).qux".
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const LocationRecorder& part_location);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parses a string surrounded by balanced braces.  Strips off the outer
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // braces and stores the enclosed string in *value.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // E.g.,
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     { foo }                     *value gets 'foo'
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     { foo { bar: box } }        *value gets 'foo { bar: box }'
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     {}                          *value gets ''
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // REQUIRES: LookingAt("{")
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When finished successfully, we are looking at the first token past
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the ending brace.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ParseUninterpretedBlock(string* value);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // =================================================================
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::Tokenizer* input_;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io::ErrorCollector* error_collector_;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SourceCodeInfo* source_code_info_;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SourceLocationTable* source_location_table_;  // legacy
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_errors_;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool require_syntax_identifier_;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool stop_after_syntax_identifier_;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string syntax_identifier_;
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Leading doc comments for the next declaration.  These are not complete
430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // yet; use ConsumeEndOfDeclaration() to get the complete comments.
431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  string upcoming_doc_comments_;
432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A table mapping (descriptor, ErrorLocation) pairs -- as reported by
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool when validating descriptors -- to line and column numbers
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// within the original source code.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is semi-obsolete:  FileDescriptorProto.source_code_info now contains
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// far more complete information about source locations.  However, as of this
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// writing you still need to use SourceLocationTable when integrating with
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DescriptorPool.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LIBPROTOBUF_EXPORT SourceLocationTable {
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SourceLocationTable();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~SourceLocationTable();
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Finds the precise location of the given error and fills in *line and
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // *column with the line and column numbers.  If not found, sets *line to
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // -1 and *column to 0 (since line = -1 is used to mean "error has no exact
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // location" in the ErrorCollector interface).  Returns true if found, false
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise.
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Find(const Message* descriptor,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            DescriptorPool::ErrorCollector::ErrorLocation location,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            int* line, int* column) const;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds a location to the table.
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Add(const Message* descriptor,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           DescriptorPool::ErrorCollector::ErrorLocation location,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           int line, int column);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clears the contents of the table.
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Clear();
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef map<
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pair<int, int> > LocationMap;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LocationMap location_map_;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace compiler
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace protobuf
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace google
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
478