~ubuntu-branches/debian/squeeze/protobuf/squeeze

« back to all changes in this revision

Viewing changes to src/google/protobuf/compiler/parser.cc

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2009-06-02 16:19:00 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090602161900-vm176i3ryt35yk91
Tags: 2.0.3-2.2
* Non-maintainer upload.
* Fix FTBFS from -2.1: don't fail when we can't clean up the java build,
  such as when openjdk isn't installed.
* Disable parallel builds, because libtool is made of fail (if binary-arch
  and build-indep run concurrently, we relink a library while it's being
  used; that doesn't work so well).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// Protocol Buffers - Google's data interchange format
2
 
// Copyright 2008 Google Inc.
 
2
// Copyright 2008 Google Inc.  All rights reserved.
3
3
// http://code.google.com/p/protobuf/
4
4
//
5
 
// Licensed under the Apache License, Version 2.0 (the "License");
6
 
// you may not use this file except in compliance with the License.
7
 
// You may obtain a copy of the License at
8
 
//
9
 
//      http://www.apache.org/licenses/LICENSE-2.0
10
 
//
11
 
// Unless required by applicable law or agreed to in writing, software
12
 
// distributed under the License is distributed on an "AS IS" BASIS,
13
 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 
// See the License for the specific language governing permissions and
15
 
// limitations under the License.
 
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.
16
30
 
17
31
// Author: kenton@google.com (Kenton Varda)
18
32
//  Based on original Protocol Buffers design by
201
215
  if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
202
216
    io::Tokenizer::ParseString(input_->current().text, output);
203
217
    input_->Next();
 
218
    // Allow C++ like concatenation of adjacent string tokens.
 
219
    while (LookingAtType(io::Tokenizer::TYPE_STRING)) {
 
220
      io::Tokenizer::ParseStringAppend(input_->current().text, output);
 
221
      input_->Next();
 
222
    }
204
223
    return true;
205
224
  } else {
206
225
    AddError(error);
294
313
    syntax_identifier_ = "proto2";
295
314
  }
296
315
 
297
 
  // Repeatedly parse statemetns until we reach the end of the file.
 
316
  // Repeatedly parse statements until we reach the end of the file.
298
317
  while (!AtEnd()) {
299
318
    if (!ParseTopLevelStatement(file)) {
300
319
      // This statement failed to parse.  Skip it, but keep looping to parse
603
622
  return true;
604
623
}
605
624
 
 
625
bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) {
 
626
  UninterpretedOption::NamePart* name = uninterpreted_option->add_name();
 
627
  string identifier;  // We parse identifiers into this string.
 
628
  if (LookingAt("(")) {  // This is an extension.
 
629
    DO(Consume("("));
 
630
    // An extension name consists of dot-separated identifiers, and may begin
 
631
    // with a dot.
 
632
    if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
 
633
      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
 
634
      name->mutable_name_part()->append(identifier);
 
635
    }
 
636
    while (LookingAt(".")) {
 
637
      DO(Consume("."));
 
638
      name->mutable_name_part()->append(".");
 
639
      DO(ConsumeIdentifier(&identifier, "Expected identifier."));
 
640
      name->mutable_name_part()->append(identifier);
 
641
    }
 
642
    DO(Consume(")"));
 
643
    name->set_is_extension(true);
 
644
  } else {  // This is a regular field.
 
645
    DO(ConsumeIdentifier(&identifier, "Expected identifier."));
 
646
    name->mutable_name_part()->append(identifier);
 
647
    name->set_is_extension(false);
 
648
  }
 
649
  return true;
 
650
}
 
651
 
 
652
// We don't interpret the option here. Instead we store it in an
 
653
// UninterpretedOption, to be interpreted later.
606
654
bool Parser::ParseOptionAssignment(Message* options) {
607
 
  Message::Reflection* reflection = options->GetReflection();
608
 
  const Descriptor* descriptor = options->GetDescriptor();
609
 
 
610
 
  // Parse name.
611
 
  string name;
612
 
  int line = input_->current().line;
613
 
  int column = input_->current().column;
614
 
  DO(ConsumeIdentifier(&name, "Expected option name."));
615
 
 
616
 
  // Is it valid?
617
 
  const FieldDescriptor* field = descriptor->FindFieldByName(name);
618
 
  if (field == NULL) {
619
 
    AddError(line, column, "Unknown option: " + name);
620
 
    return false;
621
 
  }
622
 
  if (field->is_repeated()) {
623
 
    AddError(line, column, "Not implemented: repeated options.");
624
 
    return false;
625
 
  }
626
 
  if (reflection->HasField(field)) {
627
 
    AddError(line, column, "Option \"" + name + "\" was already set.");
628
 
    return false;
629
 
  }
630
 
 
631
 
  // Are we trying to assign a member of a message?
632
 
  if (LookingAt(".")) {
633
 
    if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
634
 
      AddError("Option \"" + name + "\" is an atomic type, not a message.");
635
 
      return false;
636
 
    }
 
655
  // Create an entry in the uninterpreted_option field.
 
656
  const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->
 
657
      FindFieldByName("uninterpreted_option");
 
658
  GOOGLE_CHECK(uninterpreted_option_field != NULL)
 
659
      << "No field named \"uninterpreted_option\" in the Options proto.";
 
660
 
 
661
  UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast<UninterpretedOption*>(
 
662
      options->GetReflection()->AddMessage(options,
 
663
                                           uninterpreted_option_field));
 
664
 
 
665
  // Parse dot-separated name.
 
666
  RecordLocation(uninterpreted_option,
 
667
                 DescriptorPool::ErrorCollector::OPTION_NAME);
 
668
 
 
669
  DO(ParseOptionNamePart(uninterpreted_option));
 
670
 
 
671
  while (LookingAt(".")) {
637
672
    DO(Consume("."));
638
 
 
639
 
    // This field is a message/group.  The user must identify a field within
640
 
    // it to set.
641
 
    return ParseOptionAssignment(reflection->MutableMessage(field));
 
673
    DO(ParseOptionNamePart(uninterpreted_option));
642
674
  }
643
675
 
644
676
  DO(Consume("="));
645
677
 
646
 
  // Parse the option value.
647
 
  switch (field->cpp_type()) {
648
 
    case FieldDescriptor::CPPTYPE_INT32: {
649
 
      uint64 value;
650
 
      bool is_negative = TryConsume("-");
651
 
      uint64 max_value = kint32max;
652
 
      if (is_negative) ++max_value;
653
 
      DO(ConsumeInteger64(max_value, &value, "Expected integer."));
654
 
      reflection->SetInt32(field, is_negative ? -value : value);
655
 
      break;
656
 
    }
657
 
 
658
 
    case FieldDescriptor::CPPTYPE_INT64: {
659
 
      uint64 value;
660
 
      bool is_negative = TryConsume("-");
661
 
      uint64 max_value = kint64max;
662
 
      if (is_negative) ++max_value;
663
 
      DO(ConsumeInteger64(max_value, &value, "Expected integer."));
664
 
      reflection->SetInt64(field, is_negative ? -value : value);
665
 
      break;
666
 
    }
667
 
 
668
 
    case FieldDescriptor::CPPTYPE_UINT32: {
669
 
      uint64 value;
670
 
      DO(ConsumeInteger64(kuint32max, &value, "Expected integer."));
671
 
      reflection->SetUInt32(field, value);
672
 
      break;
673
 
    }
674
 
 
675
 
    case FieldDescriptor::CPPTYPE_UINT64: {
676
 
      uint64 value;
677
 
      DO(ConsumeInteger64(kuint64max, &value, "Expected integer."));
678
 
      reflection->SetUInt64(field, value);
679
 
      break;
680
 
    }
681
 
 
682
 
    case FieldDescriptor::CPPTYPE_DOUBLE: {
683
 
      double value;
684
 
      bool is_negative = TryConsume("-");
685
 
      DO(ConsumeNumber(&value, "Expected number."));
686
 
      reflection->SetDouble(field, is_negative ? -value : value);
687
 
      break;
688
 
    }
689
 
 
690
 
    case FieldDescriptor::CPPTYPE_FLOAT: {
691
 
      double value;
692
 
      bool is_negative = TryConsume("-");
693
 
      DO(ConsumeNumber(&value, "Expected number."));
694
 
      reflection->SetFloat(field, is_negative ? -value : value);
695
 
      break;
696
 
    }
697
 
 
698
 
    case FieldDescriptor::CPPTYPE_BOOL:
699
 
      if (TryConsume("true")) {
700
 
        reflection->SetBool(field, true);
701
 
      } else if (TryConsume("false")) {
702
 
        reflection->SetBool(field, false);
 
678
  RecordLocation(uninterpreted_option,
 
679
                 DescriptorPool::ErrorCollector::OPTION_VALUE);
 
680
 
 
681
  // All values are a single token, except for negative numbers, which consist
 
682
  // of a single '-' symbol, followed by a positive number.
 
683
  bool is_negative = TryConsume("-");
 
684
 
 
685
  switch (input_->current().type) {
 
686
    case io::Tokenizer::TYPE_START:
 
687
      GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read.";
 
688
      return false;
 
689
 
 
690
    case io::Tokenizer::TYPE_END:
 
691
      AddError("Unexpected end of stream while parsing option value.");
 
692
      return false;
 
693
 
 
694
    case io::Tokenizer::TYPE_IDENTIFIER: {
 
695
      if (is_negative) {
 
696
        AddError("Invalid '-' symbol before identifier.");
 
697
        return false;
 
698
      }
 
699
      string value;
 
700
      DO(ConsumeIdentifier(&value, "Expected identifier."));
 
701
      uninterpreted_option->set_identifier_value(value);
 
702
      break;
 
703
    }
 
704
 
 
705
    case io::Tokenizer::TYPE_INTEGER: {
 
706
      uint64 value;
 
707
      uint64 max_value =
 
708
          is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
 
709
      DO(ConsumeInteger64(max_value, &value, "Expected integer."));
 
710
      if (is_negative) {
 
711
        uninterpreted_option->set_negative_int_value(-value);
703
712
      } else {
704
 
        AddError("Expected \"true\" or \"false\".");
705
 
        return false;
706
 
      }
707
 
      break;
708
 
 
709
 
    case FieldDescriptor::CPPTYPE_ENUM: {
710
 
      string value_name;
711
 
      int value_line = input_->current().line;
712
 
      int value_column = input_->current().column;
713
 
      DO(ConsumeIdentifier(&value_name, "Expected enum value."));
714
 
      const EnumValueDescriptor* value =
715
 
        field->enum_type()->FindValueByName(value_name);
716
 
      if (value == NULL) {
717
 
        AddError(value_line, value_column,
718
 
          "Enum type \"" + field->enum_type()->full_name() + "\" has no value "
719
 
          "named \"" + value_name + "\".");
720
 
        return false;
721
 
      }
722
 
      reflection->SetEnum(field, value);
723
 
      break;
724
 
    }
725
 
 
726
 
    case FieldDescriptor::CPPTYPE_STRING: {
 
713
        uninterpreted_option->set_positive_int_value(value);
 
714
      }
 
715
      break;
 
716
    }
 
717
 
 
718
    case io::Tokenizer::TYPE_FLOAT: {
 
719
      double value;
 
720
      DO(ConsumeNumber(&value, "Expected number."));
 
721
      uninterpreted_option->set_double_value(is_negative ? -value : value);
 
722
      break;
 
723
    }
 
724
 
 
725
    case io::Tokenizer::TYPE_STRING: {
 
726
      if (is_negative) {
 
727
        AddError("Invalid '-' symbol before string.");
 
728
        return false;
 
729
      }
727
730
      string value;
728
731
      DO(ConsumeString(&value, "Expected string."));
729
 
      reflection->SetString(field, value);
 
732
      uninterpreted_option->set_string_value(value);
730
733
      break;
731
734
    }
732
735
 
733
 
    case FieldDescriptor::CPPTYPE_MESSAGE: {
734
 
      // TODO(kenton):  Allow use of protocol buffer text format here?
735
 
      AddError("\"" + name + "\" is a message.  To set fields within it, use "
736
 
               "syntax like \"" + name + ".foo = value\".");
 
736
    case io::Tokenizer::TYPE_SYMBOL:
 
737
      AddError("Expected option value.");
737
738
      return false;
738
 
      break;
739
 
    }
740
739
  }
741
740
 
742
741
  return true;
870
869
  if (is_negative) number *= -1;
871
870
  enum_value->set_number(number);
872
871
 
873
 
  // TODO(kenton):  Options for enum values?
 
872
  DO(ParseEnumConstantOptions(enum_value));
874
873
 
875
874
  DO(Consume(";"));
876
875
 
877
876
  return true;
878
877
}
879
878
 
 
879
bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) {
 
880
  if (!TryConsume("[")) return true;
 
881
 
 
882
  do {
 
883
    DO(ParseOptionAssignment(value->mutable_options()));
 
884
  } while (TryConsume(","));
 
885
 
 
886
  DO(Consume("]"));
 
887
  return true;
 
888
}
 
889
 
880
890
// -------------------------------------------------------------------
881
891
// Services
882
892
 
1034
1044
bool Parser::ParsePackage(FileDescriptorProto* file) {
1035
1045
  if (file->has_package()) {
1036
1046
    AddError("Multiple package definitions.");
 
1047
    // Don't append the new package to the old one.  Just replace it.  Not
 
1048
    // that it really matters since this is an error anyway.
 
1049
    file->clear_package();
1037
1050
  }
1038
1051
 
1039
1052
  DO(Consume("package"));