[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 7/7] qapi: Simplify QAPIDoc implements its state mac
From: |
Markus Armbruster |
Subject: |
[Qemu-devel] [PATCH 7/7] qapi: Simplify QAPIDoc implements its state machine |
Date: |
Thu, 6 Jun 2019 17:38:03 +0200 |
QAPIDoc uses a state machine to for processing of documentation lines.
Its state is encoded as an enum QAPIDoc._state (well, as enum-like
class actually, thanks to our infatuation with Python 2).
All we ever do with the state is calling the state's function to
process a line of documentation. The enum values effectively serve as
handles for the functions.
Eliminate the rather wordy indirection: store the function to call in
QAPIDoc._append_line. Update and improve comments.
Signed-off-by: Markus Armbruster <address@hidden>
---
scripts/qapi/common.py | 125 ++++++++++++++++++++++-------------------
1 file changed, 68 insertions(+), 57 deletions(-)
diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py
index 1164301edf..d61bfdc526 100644
--- a/scripts/qapi/common.py
+++ b/scripts/qapi/common.py
@@ -102,6 +102,24 @@ 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)
+
+ * features sections: a description of each feature flag
+
+ * 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,26 +138,6 @@ class QAPIDoc(object):
def connect(self, member):
self.member = member
- class DocPart:
- """
- Describes which part of the documentation we're parsing right now.
-
- 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 FEATURES part: description of each feature,
- * 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
- FEATURES = 3
- VARIOUS = 4
-
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.
@@ -156,7 +154,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."""
@@ -171,21 +169,10 @@ class QAPIDoc(object):
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 body section: ._append_line is ._append_body_line
+ * An argument section: ._append_line is ._append_args_line
+ * A features section: ._append_line is ._append_features_line
+ * An additional section: ._append_line is ._append_various_line
"""
line = line[1:]
if not line:
@@ -195,17 +182,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.FEATURES:
- self._append_features_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()
@@ -219,6 +196,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
@@ -230,38 +220,49 @@ 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 line == 'Features:':
- self._part = QAPIDoc.DocPart.FEATURES
+ self._append_line = self._append_features_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()):
if line == 'Features:':
- self._part = QAPIDoc.DocPart.FEATURES
+ self._append_line = self._append_features_line
else:
self._start_section()
- self._part = QAPIDoc.DocPart.VARIOUS
+ self._append_line = self._append_various_line
self._append_various_line(line)
return
@@ -274,19 +275,29 @@ class QAPIDoc(object):
line = line[len(name)+1:]
self._start_features_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(':'):
--
2.21.0
- [Qemu-devel] [PATCH 0/7] file-posix: Add dynamic-auto-read-only QAPI feature, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 4/7] qapi: Disentangle QAPIDoc code, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 6/7] file-posix: Add dynamic-auto-read-only QAPI feature, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 3/7] tests/qapi-schema: Error case tests for features in structs, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 5/7] qapi: Allow documentation for features, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 7/7] qapi: Simplify QAPIDoc implements its state machine,
Markus Armbruster <=
- [Qemu-devel] [PATCH 1/7] qapi: Add feature flags to struct types, Markus Armbruster, 2019/06/06
- [Qemu-devel] [PATCH 2/7] tests/qapi-schema: Test for good feature lists in structs, Markus Armbruster, 2019/06/06
- Re: [Qemu-devel] [PATCH 0/7] file-posix: Add dynamic-auto-read-only QAPI feature, Kevin Wolf, 2019/06/07
- Re: [Qemu-devel] [PATCH 0/7] file-posix: Add dynamic-auto-read-only QAPI feature, Markus Armbruster, 2019/06/12