diff --git a/docs/html/md__compiler.html b/docs/html/md__compiler.html
index 6ae87ed392403fd57ae9d3edb7e6bdfcfea529a9..9ab104fe907b6a3e55ce3ee1df698150dccb266f 100644
--- a/docs/html/md__compiler.html
+++ b/docs/html/md__compiler.html
@@ -84,7 +84,7 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});
 <li><code>--gen-mutable</code> : Generate additional non-const accessors for mutating FlatBuffers in-place.</li>
 <li><code>--gen-onefile</code> : Generate single output file (useful for C#)</li>
 <li><code>--raw-binary</code> : Allow binaries without a file_indentifier to be read. This may crash flatc given a mismatched schema.</li>
-<li><code>--proto</code>: Expect input files to be .proto files (protocol buffers). Output the corresponding .fbs file. Currently supports: <code>package</code>, <code>message</code>, <code>enum</code>. Does not support, but will skip without error: <code>import</code>, <code>option</code>. Does not support, will generate error: <code>service</code>, <code>extend</code>, <code>extensions</code>, <code>oneof</code>, <code>group</code>, custom options, nested declarations.</li>
+<li><code>--proto</code>: Expect input files to be .proto files (protocol buffers). Output the corresponding .fbs file. Currently supports: <code>package</code>, <code>message</code>, <code>enum</code>, nested declarations. Does not support, but will skip without error: <code>import</code>, <code>option</code>. Does not support, will generate error: <code>service</code>, <code>extend</code>, <code>extensions</code>, <code>oneof</code>, <code>group</code>, custom options.</li>
 <li><code>--schema</code>: Serialize schemas instead of JSON (use with -b). This will output a binary version of the specified schema that itself corresponds to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality. </li>
 </ul>
 </div></div><!-- contents -->
diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md
index e4663e172767020993c625b6e8f1889c9fa430cf..ebcdd70d601806aadaad253dc1d354c0a73223f3 100755
--- a/docs/source/Compiler.md
+++ b/docs/source/Compiler.md
@@ -71,10 +71,10 @@ be generated for each file processed:
 
 -   `--proto`: Expect input files to be .proto files (protocol buffers).
     Output the corresponding .fbs file.
-    Currently supports: `package`, `message`, `enum`.
+    Currently supports: `package`, `message`, `enum`, nested declarations.
     Does not support, but will skip without error: `import`, `option`.
     Does not support, will generate error: `service`, `extend`, `extensions`,
-    `oneof`, `group`, custom options, nested declarations.
+    `oneof`, `group`, custom options.
 
 -   `--schema`: Serialize schemas instead of JSON (use with -b). This will
     output a binary version of the specified schema that itself corresponds
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index d5aa31201ea3631a39678e2527f6e4726f9b17e0..c7c9d6d09d050f2d109435e62d31def9a4436916 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -1052,45 +1052,50 @@ void Parser::ParseProtoDecl() {
     struct_def.doc_comment = struct_comment;
     Expect('{');
     while (token_ != '}') {
-      std::vector<std::string> field_comment = doc_comment_;
-      // Parse the qualifier.
-      bool required = false;
-      bool repeated = false;
-      if (attribute_ == "optional") {
-        // This is the default.
-      } else if (attribute_ == "required") {
-        required = true;
-      } else if (attribute_ == "repeated") {
-        repeated = true;
+      if (attribute_ == "message" || attribute_ == "enum") {
+        // Nested declarations.
+        ParseProtoDecl();
       } else {
-        Error("expecting optional/required/repeated, got: " + attribute_);
-      }
-      Type type = ParseTypeFromProtoType();
-      // Repeated elements get mapped to a vector.
-      if (repeated) {
-        type.element = type.base_type;
-        type.base_type = BASE_TYPE_VECTOR;
-      }
-      std::string name = attribute_;
-      Expect(kTokenIdentifier);
-      // Parse the field id. Since we're just translating schemas, not
-      // any kind of binary compatibility, we can safely ignore these, and
-      // assign our own.
-      Expect('=');
-      Expect(kTokenIntegerConstant);
-      auto &field = AddField(struct_def, name, type);
-      field.doc_comment = field_comment;
-      if (!IsScalar(type.base_type)) field.required = required;
-      // See if there's a default specified.
-      if (IsNext('[')) {
-        if (attribute_ != "default") Error("\'default\' expected");
-        Next();
+        std::vector<std::string> field_comment = doc_comment_;
+        // Parse the qualifier.
+        bool required = false;
+        bool repeated = false;
+        if (attribute_ == "optional") {
+          // This is the default.
+        } else if (attribute_ == "required") {
+          required = true;
+        } else if (attribute_ == "repeated") {
+          repeated = true;
+        } else {
+          Error("expecting optional/required/repeated, got: " + attribute_);
+        }
+        Type type = ParseTypeFromProtoType();
+        // Repeated elements get mapped to a vector.
+        if (repeated) {
+          type.element = type.base_type;
+          type.base_type = BASE_TYPE_VECTOR;
+        }
+        std::string name = attribute_;
+        Expect(kTokenIdentifier);
+        // Parse the field id. Since we're just translating schemas, not
+        // any kind of binary compatibility, we can safely ignore these, and
+        // assign our own.
         Expect('=');
-        field.value.constant = attribute_;
-        Next();
-        Expect(']');
+        Expect(kTokenIntegerConstant);
+        auto &field = AddField(struct_def, name, type);
+        field.doc_comment = field_comment;
+        if (!IsScalar(type.base_type)) field.required = required;
+        // See if there's a default specified.
+        if (IsNext('[')) {
+          if (attribute_ != "default") Error("\'default\' expected");
+          Next();
+          Expect('=');
+          field.value.constant = attribute_;
+          Next();
+          Expect(']');
+        }
+        Expect(';');
       }
-      Expect(';');
     }
     Next();
   } else if (attribute_ == "enum") {
diff --git a/tests/prototest/test.golden b/tests/prototest/test.golden
index 767a8bc0a3f1f8e8b007223c001106d31a2fea43..7082ad2d84b917f4475cce2de1f2a8a8b15f595a 100644
--- a/tests/prototest/test.golden
+++ b/tests/prototest/test.golden
@@ -9,12 +9,6 @@ enum ProtoEnum : short {
   BAR = 5,
 }
 
-table OtherMessage {
-  a:double;
-  /// doc comment for b.
-  b:float = 3.14149;
-}
-
 /// 2nd table doc comment with
 /// many lines.
 table ProtoMessage {
@@ -39,3 +33,9 @@ table ProtoMessage {
   o:[string];
 }
 
+table OtherMessage {
+  a:double;
+  /// doc comment for b.
+  b:float = 3.14149;
+}
+
diff --git a/tests/prototest/test.proto b/tests/prototest/test.proto
index 0ca4a2a6a01469f0613477b29dd12e3bfa2df29d..af5b66d750fa47b568be5f204344b9db1b0f876b 100644
--- a/tests/prototest/test.proto
+++ b/tests/prototest/test.proto
@@ -12,16 +12,16 @@ enum ProtoEnum {
   BAR = 5;
 }
 
-// Ignored non-doc comment.
-message OtherMessage {
-  optional double a = 26;
-  /// doc comment for b.
-  optional float b = 32 [default = 3.14149];
-}
-
 /// 2nd table doc comment with
 /// many lines.
 message ProtoMessage {
+  // Ignored non-doc comment.
+  // A nested message declaration, will be moved to top level in .fbs
+  message OtherMessage {
+    optional double a = 26;
+    /// doc comment for b.
+    optional float b = 32 [default = 3.14149];
+  }
   optional int32 c = 12 [default = 16];
   optional int64 d = 1 [default = 0];
   optional uint32 p = 1;