summaryrefslogtreecommitdiff
path: root/lib/sly/docparse.py
diff options
context:
space:
mode:
authorDaniel Friesel <daniel.friesel@uos.de>2019-12-12 17:33:13 +0100
committerDaniel Friesel <daniel.friesel@uos.de>2019-12-12 17:33:13 +0100
commitff6fc70456354b23663bee037c5e737a2b437ca8 (patch)
tree57397e592e664bf5f20b72032be887557bc2df08 /lib/sly/docparse.py
parent575a33b819d29ee99fa7d4264a943043d1d64032 (diff)
import SLY
Diffstat (limited to 'lib/sly/docparse.py')
-rw-r--r--lib/sly/docparse.py60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/sly/docparse.py b/lib/sly/docparse.py
new file mode 100644
index 0000000..d5a83ce
--- /dev/null
+++ b/lib/sly/docparse.py
@@ -0,0 +1,60 @@
+# docparse.py
+#
+# Support doc-string parsing classes
+
+__all__ = [ 'DocParseMeta' ]
+
+class DocParseMeta(type):
+ '''
+ Metaclass that processes the class docstring through a parser and
+ incorporates the result into the resulting class definition. This
+ allows Python classes to be defined with alternative syntax.
+ To use this class, you first need to define a lexer and parser:
+
+ from sly import Lexer, Parser
+ class MyLexer(Lexer):
+ ...
+
+ class MyParser(Parser):
+ ...
+
+ You then need to define a metaclass that inherits from DocParseMeta.
+ This class must specify the associated lexer and parser classes.
+ For example:
+
+ class MyDocParseMeta(DocParseMeta):
+ lexer = MyLexer
+ parser = MyParser
+
+ This metaclass is then used as a base for processing user-defined
+ classes:
+
+ class Base(metaclass=MyDocParseMeta):
+ pass
+
+ class Spam(Base):
+ """
+ doc string is parsed
+ ...
+ """
+
+ It is expected that the MyParser() class would return a dictionary.
+ This dictionary is used to create the final class Spam in this example.
+ '''
+
+ @staticmethod
+ def __new__(meta, clsname, bases, clsdict):
+ if '__doc__' in clsdict:
+ lexer = meta.lexer()
+ parser = meta.parser()
+ lexer.cls_name = parser.cls_name = clsname
+ lexer.cls_qualname = parser.cls_qualname = clsdict['__qualname__']
+ lexer.cls_module = parser.cls_module = clsdict['__module__']
+ parsedict = parser.parse(lexer.tokenize(clsdict['__doc__']))
+ assert isinstance(parsedict, dict), 'Parser must return a dictionary'
+ clsdict.update(parsedict)
+ return super().__new__(meta, clsname, bases, clsdict)
+
+ @classmethod
+ def __init_subclass__(cls):
+ assert hasattr(cls, 'parser') and hasattr(cls, 'lexer')