diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index b42dad9b36..004b68df5c 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -102,6 +102,22 @@ class QAPISemError(QAPIError):
 
 
 class QAPIDoc(object):
+    """
+    A documentation comment block, either expression or free-form
+
+    Expression documentation blocks consist of
+
+    * a body section: one line naming the expression, followed by an
+      overview (any number of lines)
+
+    * argument sections: a description of each argument (for commands
+      and events) or member (for structs, unions and alternates)
+
+    * additional (non-argument) sections, possibly tagged
+
+    Free-form documentation blocks consist only of a body section.
+    """
+
     class Section(object):
         def __init__(self, name=None):
             # optional section name (argument/member or section name)
@@ -120,22 +136,6 @@ class QAPIDoc(object):
         def connect(self, member):
             self.member = member
 
-    class DocPart:
-        """
-        Expression documentation blocks consist of
-        * a BODY part: first line naming the expression, plus an
-          optional overview
-        * an ARGS part: description of each argument (for commands and
-          events) or member (for structs, unions and alternates),
-        * a VARIOUS part: optional tagged sections.
-
-        Free-form documentation blocks consist only of a BODY part.
-        """
-        # TODO Make it a subclass of Enum when Python 2 support is removed
-        BODY = 1
-        ARGS = 2
-        VARIOUS = 3
-
     def __init__(self, parser, info):
         # self._parser is used to report errors with QAPIParseError.  The
         # resulting error position depends on the state of the parser.
@@ -151,7 +151,7 @@ class QAPIDoc(object):
         self.sections = []
         # the current section
         self._section = self.body
-        self._part = QAPIDoc.DocPart.BODY
+        self._append_line = self._append_body_line
 
     def has_section(self, name):
         """Return True if we have a section with this name."""
@@ -164,20 +164,11 @@ class QAPIDoc(object):
         """
         Parse a comment line and add it to the documentation.
 
-        The way that the line is dealt with depends on which part of the
-        documentation we're parsing right now:
-
-        BODY means that we're ready to process free-form text into self.body. A
-        symbol name is only allowed if no other text was parsed yet. It is
-        interpreted as the symbol name that describes the currently documented
-        object. On getting the second symbol name, we proceed to ARGS.
-
-        ARGS means that we're parsing the arguments section. Any symbol name is
-        interpreted as an argument and an ArgSection is created for it.
-
-        VARIOUS is the final part where free-form sections may appear. This
-        includes named sections such as "Return:" as well as unnamed
-        paragraphs. Symbols are not allowed any more in this part.
+        The way that the line is dealt with depends on which part of
+        the documentation we're parsing right now:
+        * The body section: ._append_line is ._append_body_line
+        * An argument section: ._append_line is ._append_args_line
+        * An additional section: ._append_line is ._append_various_line
         """
         line = line[1:]
         if not line:
@@ -187,15 +178,7 @@ class QAPIDoc(object):
         if line[0] != ' ':
             raise QAPIParseError(self._parser, "Missing space after #")
         line = line[1:]
-
-        if self._part == QAPIDoc.DocPart.BODY:
-            self._append_body_line(line)
-        elif self._part == QAPIDoc.DocPart.ARGS:
-            self._append_args_line(line)
-        elif self._part == QAPIDoc.DocPart.VARIOUS:
-            self._append_various_line(line)
-        else:
-            assert False
+        self._append_line(line)
 
     def end_comment(self):
         self._end_section()
@@ -209,6 +192,19 @@ class QAPIDoc(object):
                         'TODO:')
 
     def _append_body_line(self, line):
+        """
+        Process a line of documentation text in the body section.
+
+        If this a symbol line and it is the section's first line, this
+        is an expression documentation block for that symbol.
+
+        If it's an expression documentation block, another symbol line
+        begins the argument section for the argument named by it, and
+        a section tag begins an additional section.  Start that
+        section and append the line to it.
+
+        Else, append the line to the current section.
+        """
         name = line.split(' ', 1)[0]
         # FIXME not nice: things like '#  @foo:' and '# @foo: ' aren't
         # recognized, and get silently treated as ordinary text
@@ -220,39 +216,60 @@ class QAPIDoc(object):
             if not self.symbol:
                 raise QAPIParseError(self._parser, "Invalid name")
         elif self.symbol:
-            # We already know that we document some symbol
+            # This is an expression documentation block
             if name.startswith('@') and name.endswith(':'):
-                self._part = QAPIDoc.DocPart.ARGS
+                self._append_line = self._append_args_line
                 self._append_args_line(line)
             elif self._is_section_tag(name):
-                self._part = QAPIDoc.DocPart.VARIOUS
+                self._append_line = self._append_various_line
                 self._append_various_line(line)
             else:
                 self._append_freeform(line.strip())
         else:
-            # This is free-form documentation without a symbol
+            # This is a free-form documentation block
             self._append_freeform(line.strip())
 
     def _append_args_line(self, line):
+        """
+        Process a line of documentation text in an argument section.
+
+        A symbol line begins the next argument section, a section tag
+        section or a non-indented line after a blank line begins an
+        additional section.  Start that section and append the line to
+        it.
+
+        Else, append the line to the current section.
+
+        """
         name = line.split(' ', 1)[0]
 
         if name.startswith('@') and name.endswith(':'):
             line = line[len(name)+1:]
             self._start_args_section(name[1:-1])
         elif self._is_section_tag(name):
-            self._part = QAPIDoc.DocPart.VARIOUS
+            self._append_line = self._append_various_line
             self._append_various_line(line)
             return
         elif (self._section.text.endswith('\n\n')
               and line and not line[0].isspace()):
             self._start_section()
-            self._part = QAPIDoc.DocPart.VARIOUS
+            self._append_line = self._append_various_line
             self._append_various_line(line)
             return
 
         self._append_freeform(line.strip())
 
     def _append_various_line(self, line):
+        """
+        Process a line of documentation text in an additional section.
+
+        A symbol line is an error.
+
+        A section tag begins an additional section.  Start that
+        section and append the line to it.
+
+        Else, append the line to the current section.
+        """
         name = line.split(' ', 1)[0]
 
         if name.startswith('@') and name.endswith(':'):
