about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py336
1 files changed, 336 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py b/.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py
new file mode 100644
index 00000000..0f7d330b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pycparser/_ast_gen.py
@@ -0,0 +1,336 @@
+#-----------------------------------------------------------------
+# _ast_gen.py
+#
+# Generates the AST Node classes from a specification given in
+# a configuration file
+#
+# The design of this module was inspired by astgen.py from the
+# Python 2.5 code-base.
+#
+# Eli Bendersky [https://eli.thegreenplace.net/]
+# License: BSD
+#-----------------------------------------------------------------
+from string import Template
+
+
+class ASTCodeGenerator(object):
+    def __init__(self, cfg_filename='_c_ast.cfg'):
+        """ Initialize the code generator from a configuration
+            file.
+        """
+        self.cfg_filename = cfg_filename
+        self.node_cfg = [NodeCfg(name, contents)
+            for (name, contents) in self.parse_cfgfile(cfg_filename)]
+
+    def generate(self, file=None):
+        """ Generates the code into file, an open file buffer.
+        """
+        src = Template(_PROLOGUE_COMMENT).substitute(
+            cfg_filename=self.cfg_filename)
+
+        src += _PROLOGUE_CODE
+        for node_cfg in self.node_cfg:
+            src += node_cfg.generate_source() + '\n\n'
+
+        file.write(src)
+
+    def parse_cfgfile(self, filename):
+        """ Parse the configuration file and yield pairs of
+            (name, contents) for each node.
+        """
+        with open(filename, "r") as f:
+            for line in f:
+                line = line.strip()
+                if not line or line.startswith('#'):
+                    continue
+                colon_i = line.find(':')
+                lbracket_i = line.find('[')
+                rbracket_i = line.find(']')
+                if colon_i < 1 or lbracket_i <= colon_i or rbracket_i <= lbracket_i:
+                    raise RuntimeError("Invalid line in %s:\n%s\n" % (filename, line))
+
+                name = line[:colon_i]
+                val = line[lbracket_i + 1:rbracket_i]
+                vallist = [v.strip() for v in val.split(',')] if val else []
+                yield name, vallist
+
+
+class NodeCfg(object):
+    """ Node configuration.
+
+        name: node name
+        contents: a list of contents - attributes and child nodes
+        See comment at the top of the configuration file for details.
+    """
+
+    def __init__(self, name, contents):
+        self.name = name
+        self.all_entries = []
+        self.attr = []
+        self.child = []
+        self.seq_child = []
+
+        for entry in contents:
+            clean_entry = entry.rstrip('*')
+            self.all_entries.append(clean_entry)
+
+            if entry.endswith('**'):
+                self.seq_child.append(clean_entry)
+            elif entry.endswith('*'):
+                self.child.append(clean_entry)
+            else:
+                self.attr.append(entry)
+
+    def generate_source(self):
+        src = self._gen_init()
+        src += '\n' + self._gen_children()
+        src += '\n' + self._gen_iter()
+        src += '\n' + self._gen_attr_names()
+        return src
+
+    def _gen_init(self):
+        src = "class %s(Node):\n" % self.name
+
+        if self.all_entries:
+            args = ', '.join(self.all_entries)
+            slots = ', '.join("'{0}'".format(e) for e in self.all_entries)
+            slots += ", 'coord', '__weakref__'"
+            arglist = '(self, %s, coord=None)' % args
+        else:
+            slots = "'coord', '__weakref__'"
+            arglist = '(self, coord=None)'
+
+        src += "    __slots__ = (%s)\n" % slots
+        src += "    def __init__%s:\n" % arglist
+
+        for name in self.all_entries + ['coord']:
+            src += "        self.%s = %s\n" % (name, name)
+
+        return src
+
+    def _gen_children(self):
+        src = '    def children(self):\n'
+
+        if self.all_entries:
+            src += '        nodelist = []\n'
+
+            for child in self.child:
+                src += (
+                    '        if self.%(child)s is not None:' +
+                    ' nodelist.append(("%(child)s", self.%(child)s))\n') % (
+                        dict(child=child))
+
+            for seq_child in self.seq_child:
+                src += (
+                    '        for i, child in enumerate(self.%(child)s or []):\n'
+                    '            nodelist.append(("%(child)s[%%d]" %% i, child))\n') % (
+                        dict(child=seq_child))
+
+            src += '        return tuple(nodelist)\n'
+        else:
+            src += '        return ()\n'
+
+        return src
+
+    def _gen_iter(self):
+        src = '    def __iter__(self):\n'
+
+        if self.all_entries:
+            for child in self.child:
+                src += (
+                    '        if self.%(child)s is not None:\n' +
+                    '            yield self.%(child)s\n') % (dict(child=child))
+
+            for seq_child in self.seq_child:
+                src += (
+                    '        for child in (self.%(child)s or []):\n'
+                    '            yield child\n') % (dict(child=seq_child))
+
+            if not (self.child or self.seq_child):
+                # Empty generator
+                src += (
+                    '        return\n' +
+                    '        yield\n')
+        else:
+            # Empty generator
+            src += (
+                '        return\n' +
+                '        yield\n')
+
+        return src
+
+    def _gen_attr_names(self):
+        src = "    attr_names = (" + ''.join("%r, " % nm for nm in self.attr) + ')'
+        return src
+
+
+_PROLOGUE_COMMENT = \
+r'''#-----------------------------------------------------------------
+# ** ATTENTION **
+# This code was automatically generated from the file:
+# $cfg_filename
+#
+# Do not modify it directly. Modify the configuration file and
+# run the generator again.
+# ** ** *** ** **
+#
+# pycparser: c_ast.py
+#
+# AST Node classes.
+#
+# Eli Bendersky [https://eli.thegreenplace.net/]
+# License: BSD
+#-----------------------------------------------------------------
+
+'''
+
+_PROLOGUE_CODE = r'''
+import sys
+
+def _repr(obj):
+    """
+    Get the representation of an object, with dedicated pprint-like format for lists.
+    """
+    if isinstance(obj, list):
+        return '[' + (',\n '.join((_repr(e).replace('\n', '\n ') for e in obj))) + '\n]'
+    else:
+        return repr(obj)
+
+class Node(object):
+    __slots__ = ()
+    """ Abstract base class for AST nodes.
+    """
+    def __repr__(self):
+        """ Generates a python representation of the current node
+        """
+        result = self.__class__.__name__ + '('
+
+        indent = ''
+        separator = ''
+        for name in self.__slots__[:-2]:
+            result += separator
+            result += indent
+            result += name + '=' + (_repr(getattr(self, name)).replace('\n', '\n  ' + (' ' * (len(name) + len(self.__class__.__name__)))))
+
+            separator = ','
+            indent = '\n ' + (' ' * len(self.__class__.__name__))
+
+        result += indent + ')'
+
+        return result
+
+    def children(self):
+        """ A sequence of all children that are Nodes
+        """
+        pass
+
+    def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None):
+        """ Pretty print the Node and all its attributes and
+            children (recursively) to a buffer.
+
+            buf:
+                Open IO buffer into which the Node is printed.
+
+            offset:
+                Initial offset (amount of leading spaces)
+
+            attrnames:
+                True if you want to see the attribute names in
+                name=value pairs. False to only see the values.
+
+            nodenames:
+                True if you want to see the actual node names
+                within their parents.
+
+            showcoord:
+                Do you want the coordinates of each Node to be
+                displayed.
+        """
+        lead = ' ' * offset
+        if nodenames and _my_node_name is not None:
+            buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ')
+        else:
+            buf.write(lead + self.__class__.__name__+ ': ')
+
+        if self.attr_names:
+            if attrnames:
+                nvlist = [(n, getattr(self,n)) for n in self.attr_names]
+                attrstr = ', '.join('%s=%s' % nv for nv in nvlist)
+            else:
+                vlist = [getattr(self, n) for n in self.attr_names]
+                attrstr = ', '.join('%s' % v for v in vlist)
+            buf.write(attrstr)
+
+        if showcoord:
+            buf.write(' (at %s)' % self.coord)
+        buf.write('\n')
+
+        for (child_name, child) in self.children():
+            child.show(
+                buf,
+                offset=offset + 2,
+                attrnames=attrnames,
+                nodenames=nodenames,
+                showcoord=showcoord,
+                _my_node_name=child_name)
+
+
+class NodeVisitor(object):
+    """ A base NodeVisitor class for visiting c_ast nodes.
+        Subclass it and define your own visit_XXX methods, where
+        XXX is the class name you want to visit with these
+        methods.
+
+        For example:
+
+        class ConstantVisitor(NodeVisitor):
+            def __init__(self):
+                self.values = []
+
+            def visit_Constant(self, node):
+                self.values.append(node.value)
+
+        Creates a list of values of all the constant nodes
+        encountered below the given node. To use it:
+
+        cv = ConstantVisitor()
+        cv.visit(node)
+
+        Notes:
+
+        *   generic_visit() will be called for AST nodes for which
+            no visit_XXX method was defined.
+        *   The children of nodes for which a visit_XXX was
+            defined will not be visited - if you need this, call
+            generic_visit() on the node.
+            You can use:
+                NodeVisitor.generic_visit(self, node)
+        *   Modeled after Python's own AST visiting facilities
+            (the ast module of Python 3.0)
+    """
+
+    _method_cache = None
+
+    def visit(self, node):
+        """ Visit a node.
+        """
+
+        if self._method_cache is None:
+            self._method_cache = {}
+
+        visitor = self._method_cache.get(node.__class__.__name__, None)
+        if visitor is None:
+            method = 'visit_' + node.__class__.__name__
+            visitor = getattr(self, method, self.generic_visit)
+            self._method_cache[node.__class__.__name__] = visitor
+
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """ Called if no explicit visitor function exists for a
+            node. Implements preorder visiting of the node.
+        """
+        for c in node:
+            self.visit(c)
+
+'''