// Path: src/main/java/com/squareup/protoparser/DataType.java
// final class MapType implements DataType {
//   public static MapType create(DataType keyType, DataType valueType) {
//     return new MapType(checkNotNull(keyType, "keyType"), checkNotNull(valueType, "valueType"));
//   }
// 
//   private final DataType keyType;
//   private final DataType valueType;
// 
//   private MapType(DataType keyType, DataType valueType) {
//     this.keyType = keyType;
//     this.valueType = valueType;
//   }
// 
//   @Override public Kind kind() {
//     return Kind.MAP;
//   }
// 
//   public DataType keyType() {
//     return keyType;
//   }
// 
//   public DataType valueType() {
//     return valueType;
//   }
// 
//   @Override public String toString() {
//     return "map<" + keyType + ", " + valueType + ">";
//   }
// 
//   @Override public boolean equals(Object obj) {
//     if (obj == this) return true;
//     if (!(obj instanceof MapType)) return false;
//     MapType other = (MapType) obj;
//     return keyType.equals(other.keyType) && valueType.equals(other.valueType);
//   }
// 
//   @Override public int hashCode() {
//     return keyType.hashCode() * 37 + valueType.hashCode();
//   }
// }
// 
// Path: src/main/java/com/squareup/protoparser/DataType.java
// final class NamedType implements DataType {
//   public static NamedType create(String name) {
//     return new NamedType(checkNotNull(name, "name"));
//   }
// 
//   private final String name;
// 
//   private NamedType(String name) {
//     this.name = name;
//   }
// 
//   public String name() {
//     return name;
//   }
// 
//   @Override public Kind kind() {
//     return Kind.NAMED;
//   }
// 
//   @Override public String toString() {
//     return name;
//   }
// 
//   @Override public boolean equals(Object obj) {
//     if (obj == this) return true;
//     if (!(obj instanceof NamedType)) return false;
//     NamedType other = (NamedType) obj;
//     return name.equals(other.name);
//   }
// 
//   @Override public int hashCode() {
//     return name.hashCode();
//   }
// }
// 
// Path: src/main/java/com/squareup/protoparser/DataType.java
// enum ScalarType implements DataType {
//   ANY,
//   BOOL,
//   BYTES,
//   DOUBLE,
//   FLOAT,
//   FIXED32,
//   FIXED64,
//   INT32,
//   INT64,
//   SFIXED32,
//   SFIXED64,
//   SINT32,
//   SINT64,
//   STRING,
//   UINT32,
//   UINT64;
// 
//   @Override public Kind kind() {
//     return Kind.SCALAR;
//   }
// 
//   @Override public String toString() {
//     return name().toLowerCase(Locale.US);
//   }
// }


import com.google.auto.value.AutoValue;
import com.squareup.protoparser.DataType.MapType;
import com.squareup.protoparser.DataType.NamedType;
import com.squareup.protoparser.DataType.ScalarType;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static com.squareup.protoparser.ProtoFile.Syntax.PROTO_2;
import static com.squareup.protoparser.ProtoFile.Syntax.PROTO_3;
import static java.nio.charset.StandardCharsets.UTF_8;
  /**
   * Adds an object or objects to a List.
   */
  private void addToList(List<Object> list, Object value) {
    if (value instanceof List) {
      list.addAll((List) value);
    } else {
      list.add(value);
    }
  }

  /**
   * Returns a list of values. This is similar to JSON with '[' and ']'
   * surrounding the list and ',' separating values.
   */
  private List<Object> readList() {
    if (readChar() != '[') throw new AssertionError();
    List<Object> result = new ArrayList<>();
    while (true) {
      if (peekChar() == ']') {
        // If we see the close brace, finish immediately. This handles [] and ,] cases.
        pos++;
        return result;
      }

      result.add(readKindAndValue().value());

      char c = peekChar();
      if (c == ',') {
        pos++;
// Path: src/main/java/com/squareup/protoparser/DataType.java
// final class MapType implements DataType {
//   public static MapType create(DataType keyType, DataType valueType) {
//     return new MapType(checkNotNull(keyType, "keyType"), checkNotNull(valueType, "valueType"));
//   }
// 
//   private final DataType keyType;
//   private final DataType valueType;
// 
//   private MapType(DataType keyType, DataType valueType) {
//     this.keyType = keyType;
//     this.valueType = valueType;
//   }
// 
//   @Override public Kind kind() {
//     return Kind.MAP;
//   }
// 
//   public DataType keyType() {
//     return keyType;
//   }
// 
//   public DataType valueType() {
//     return valueType;
//   }
// 
//   @Override public String toString() {
//     return "map<" + keyType + ", " + valueType + ">";
//   }
// 
//   @Override public boolean equals(Object obj) {
//     if (obj == this) return true;
//     if (!(obj instanceof MapType)) return false;
//     MapType other = (MapType) obj;
//     return keyType.equals(other.keyType) && valueType.equals(other.valueType);
//   }
// 
//   @Override public int hashCode() {
//     return keyType.hashCode() * 37 + valueType.hashCode();
//   }
// }
// 
// Path: src/main/java/com/squareup/protoparser/DataType.java
// final class NamedType implements DataType {
//   public static NamedType create(String name) {
//     return new NamedType(checkNotNull(name, "name"));
//   }
// 
//   private final String name;
// 
//   private NamedType(String name) {
//     this.name = name;
//   }
// 
//   public String name() {
//     return name;
//   }
// 
//   @Override public Kind kind() {
//     return Kind.NAMED;
//   }
// 
//   @Override public String toString() {
//     return name;
//   }
// 
//   @Override public boolean equals(Object obj) {
//     if (obj == this) return true;
//     if (!(obj instanceof NamedType)) return false;
//     NamedType other = (NamedType) obj;
//     return name.equals(other.name);
//   }
// 
//   @Override public int hashCode() {
//     return name.hashCode();
//   }
// }
// 
// Path: src/main/java/com/squareup/protoparser/DataType.java
// enum ScalarType implements DataType {
//   ANY,
//   BOOL,
//   BYTES,
//   DOUBLE,
//   FLOAT,
//   FIXED32,
//   FIXED64,
//   INT32,
//   INT64,
//   SFIXED32,
//   SFIXED64,
//   SINT32,
//   SINT64,
//   STRING,
//   UINT32,
//   UINT64;
// 
//   @Override public Kind kind() {
//     return Kind.SCALAR;
//   }
// 
//   @Override public String toString() {
//     return name().toLowerCase(Locale.US);
//   }
// }


// Path: src/main/java/com/squareup/protoparser/ProtoParser.java
import com.google.auto.value.AutoValue;
import com.squareup.protoparser.DataType.MapType;
import com.squareup.protoparser.DataType.NamedType;
import com.squareup.protoparser.DataType.ScalarType;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static com.squareup.protoparser.ProtoFile.Syntax.PROTO_2;
import static com.squareup.protoparser.ProtoFile.Syntax.PROTO_3;
import static java.nio.charset.StandardCharsets.UTF_8;

  /**
   * Adds an object or objects to a List.
   */
  private void addToList(List<Object> list, Object value) {
    if (value instanceof List) {
      list.addAll((List) value);
    } else {
      list.add(value);
    }
  }

  /**
   * Returns a list of values. This is similar to JSON with '[' and ']'
   * surrounding the list and ',' separating values.
   */
  private List<Object> readList() {
    if (readChar() != '[') throw new AssertionError();
    List<Object> result = new ArrayList<>();
    while (true) {
      if (peekChar() == ']') {
        // If we see the close brace, finish immediately. This handles [] and ,] cases.
        pos++;
        return result;
      }

      result.add(readKindAndValue().value());

      char c = peekChar();
      if (c == ',') {
        pos++;
      } else if (c != ']') {