pycparser 2.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycparser/__init__.py +93 -0
- pycparser/_ast_gen.py +336 -0
- pycparser/_build_tables.py +40 -0
- pycparser/_c_ast.cfg +195 -0
- pycparser/ast_transforms.py +164 -0
- pycparser/c_ast.py +1125 -0
- pycparser/c_generator.py +502 -0
- pycparser/c_lexer.py +555 -0
- pycparser/c_parser.py +1950 -0
- pycparser/lextab.py +10 -0
- pycparser/ply/__init__.py +5 -0
- pycparser/ply/cpp.py +905 -0
- pycparser/ply/ctokens.py +133 -0
- pycparser/ply/lex.py +1099 -0
- pycparser/ply/yacc.py +3494 -0
- pycparser/ply/ygen.py +74 -0
- pycparser/plyparser.py +133 -0
- pycparser/yacctab.py +369 -0
- pycparser-2.22.dist-info/LICENSE +27 -0
- pycparser-2.22.dist-info/METADATA +28 -0
- pycparser-2.22.dist-info/RECORD +23 -0
- pycparser-2.22.dist-info/WHEEL +5 -0
- pycparser-2.22.dist-info/top_level.txt +1 -0
pycparser/__init__.py
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#-----------------------------------------------------------------
|
|
2
|
+
# pycparser: __init__.py
|
|
3
|
+
#
|
|
4
|
+
# This package file exports some convenience functions for
|
|
5
|
+
# interacting with pycparser
|
|
6
|
+
#
|
|
7
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
8
|
+
# License: BSD
|
|
9
|
+
#-----------------------------------------------------------------
|
|
10
|
+
__all__ = ['c_lexer', 'c_parser', 'c_ast']
|
|
11
|
+
__version__ = '2.22'
|
|
12
|
+
|
|
13
|
+
import io
|
|
14
|
+
from subprocess import check_output
|
|
15
|
+
from .c_parser import CParser
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def preprocess_file(filename, cpp_path='cpp', cpp_args=''):
|
|
19
|
+
""" Preprocess a file using cpp.
|
|
20
|
+
|
|
21
|
+
filename:
|
|
22
|
+
Name of the file you want to preprocess.
|
|
23
|
+
|
|
24
|
+
cpp_path:
|
|
25
|
+
cpp_args:
|
|
26
|
+
Refer to the documentation of parse_file for the meaning of these
|
|
27
|
+
arguments.
|
|
28
|
+
|
|
29
|
+
When successful, returns the preprocessed file's contents.
|
|
30
|
+
Errors from cpp will be printed out.
|
|
31
|
+
"""
|
|
32
|
+
path_list = [cpp_path]
|
|
33
|
+
if isinstance(cpp_args, list):
|
|
34
|
+
path_list += cpp_args
|
|
35
|
+
elif cpp_args != '':
|
|
36
|
+
path_list += [cpp_args]
|
|
37
|
+
path_list += [filename]
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
# Note the use of universal_newlines to treat all newlines
|
|
41
|
+
# as \n for Python's purpose
|
|
42
|
+
text = check_output(path_list, universal_newlines=True)
|
|
43
|
+
except OSError as e:
|
|
44
|
+
raise RuntimeError("Unable to invoke 'cpp'. " +
|
|
45
|
+
'Make sure its path was passed correctly\n' +
|
|
46
|
+
('Original error: %s' % e))
|
|
47
|
+
|
|
48
|
+
return text
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def parse_file(filename, use_cpp=False, cpp_path='cpp', cpp_args='',
|
|
52
|
+
parser=None, encoding=None):
|
|
53
|
+
""" Parse a C file using pycparser.
|
|
54
|
+
|
|
55
|
+
filename:
|
|
56
|
+
Name of the file you want to parse.
|
|
57
|
+
|
|
58
|
+
use_cpp:
|
|
59
|
+
Set to True if you want to execute the C pre-processor
|
|
60
|
+
on the file prior to parsing it.
|
|
61
|
+
|
|
62
|
+
cpp_path:
|
|
63
|
+
If use_cpp is True, this is the path to 'cpp' on your
|
|
64
|
+
system. If no path is provided, it attempts to just
|
|
65
|
+
execute 'cpp', so it must be in your PATH.
|
|
66
|
+
|
|
67
|
+
cpp_args:
|
|
68
|
+
If use_cpp is True, set this to the command line arguments strings
|
|
69
|
+
to cpp. Be careful with quotes - it's best to pass a raw string
|
|
70
|
+
(r'') here. For example:
|
|
71
|
+
r'-I../utils/fake_libc_include'
|
|
72
|
+
If several arguments are required, pass a list of strings.
|
|
73
|
+
|
|
74
|
+
encoding:
|
|
75
|
+
Encoding to use for the file to parse
|
|
76
|
+
|
|
77
|
+
parser:
|
|
78
|
+
Optional parser object to be used instead of the default CParser
|
|
79
|
+
|
|
80
|
+
When successful, an AST is returned. ParseError can be
|
|
81
|
+
thrown if the file doesn't parse successfully.
|
|
82
|
+
|
|
83
|
+
Errors from cpp will be printed out.
|
|
84
|
+
"""
|
|
85
|
+
if use_cpp:
|
|
86
|
+
text = preprocess_file(filename, cpp_path, cpp_args)
|
|
87
|
+
else:
|
|
88
|
+
with io.open(filename, encoding=encoding) as f:
|
|
89
|
+
text = f.read()
|
|
90
|
+
|
|
91
|
+
if parser is None:
|
|
92
|
+
parser = CParser()
|
|
93
|
+
return parser.parse(text, filename)
|
pycparser/_ast_gen.py
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#-----------------------------------------------------------------
|
|
2
|
+
# _ast_gen.py
|
|
3
|
+
#
|
|
4
|
+
# Generates the AST Node classes from a specification given in
|
|
5
|
+
# a configuration file
|
|
6
|
+
#
|
|
7
|
+
# The design of this module was inspired by astgen.py from the
|
|
8
|
+
# Python 2.5 code-base.
|
|
9
|
+
#
|
|
10
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
11
|
+
# License: BSD
|
|
12
|
+
#-----------------------------------------------------------------
|
|
13
|
+
from string import Template
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ASTCodeGenerator(object):
|
|
17
|
+
def __init__(self, cfg_filename='_c_ast.cfg'):
|
|
18
|
+
""" Initialize the code generator from a configuration
|
|
19
|
+
file.
|
|
20
|
+
"""
|
|
21
|
+
self.cfg_filename = cfg_filename
|
|
22
|
+
self.node_cfg = [NodeCfg(name, contents)
|
|
23
|
+
for (name, contents) in self.parse_cfgfile(cfg_filename)]
|
|
24
|
+
|
|
25
|
+
def generate(self, file=None):
|
|
26
|
+
""" Generates the code into file, an open file buffer.
|
|
27
|
+
"""
|
|
28
|
+
src = Template(_PROLOGUE_COMMENT).substitute(
|
|
29
|
+
cfg_filename=self.cfg_filename)
|
|
30
|
+
|
|
31
|
+
src += _PROLOGUE_CODE
|
|
32
|
+
for node_cfg in self.node_cfg:
|
|
33
|
+
src += node_cfg.generate_source() + '\n\n'
|
|
34
|
+
|
|
35
|
+
file.write(src)
|
|
36
|
+
|
|
37
|
+
def parse_cfgfile(self, filename):
|
|
38
|
+
""" Parse the configuration file and yield pairs of
|
|
39
|
+
(name, contents) for each node.
|
|
40
|
+
"""
|
|
41
|
+
with open(filename, "r") as f:
|
|
42
|
+
for line in f:
|
|
43
|
+
line = line.strip()
|
|
44
|
+
if not line or line.startswith('#'):
|
|
45
|
+
continue
|
|
46
|
+
colon_i = line.find(':')
|
|
47
|
+
lbracket_i = line.find('[')
|
|
48
|
+
rbracket_i = line.find(']')
|
|
49
|
+
if colon_i < 1 or lbracket_i <= colon_i or rbracket_i <= lbracket_i:
|
|
50
|
+
raise RuntimeError("Invalid line in %s:\n%s\n" % (filename, line))
|
|
51
|
+
|
|
52
|
+
name = line[:colon_i]
|
|
53
|
+
val = line[lbracket_i + 1:rbracket_i]
|
|
54
|
+
vallist = [v.strip() for v in val.split(',')] if val else []
|
|
55
|
+
yield name, vallist
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class NodeCfg(object):
|
|
59
|
+
""" Node configuration.
|
|
60
|
+
|
|
61
|
+
name: node name
|
|
62
|
+
contents: a list of contents - attributes and child nodes
|
|
63
|
+
See comment at the top of the configuration file for details.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(self, name, contents):
|
|
67
|
+
self.name = name
|
|
68
|
+
self.all_entries = []
|
|
69
|
+
self.attr = []
|
|
70
|
+
self.child = []
|
|
71
|
+
self.seq_child = []
|
|
72
|
+
|
|
73
|
+
for entry in contents:
|
|
74
|
+
clean_entry = entry.rstrip('*')
|
|
75
|
+
self.all_entries.append(clean_entry)
|
|
76
|
+
|
|
77
|
+
if entry.endswith('**'):
|
|
78
|
+
self.seq_child.append(clean_entry)
|
|
79
|
+
elif entry.endswith('*'):
|
|
80
|
+
self.child.append(clean_entry)
|
|
81
|
+
else:
|
|
82
|
+
self.attr.append(entry)
|
|
83
|
+
|
|
84
|
+
def generate_source(self):
|
|
85
|
+
src = self._gen_init()
|
|
86
|
+
src += '\n' + self._gen_children()
|
|
87
|
+
src += '\n' + self._gen_iter()
|
|
88
|
+
src += '\n' + self._gen_attr_names()
|
|
89
|
+
return src
|
|
90
|
+
|
|
91
|
+
def _gen_init(self):
|
|
92
|
+
src = "class %s(Node):\n" % self.name
|
|
93
|
+
|
|
94
|
+
if self.all_entries:
|
|
95
|
+
args = ', '.join(self.all_entries)
|
|
96
|
+
slots = ', '.join("'{0}'".format(e) for e in self.all_entries)
|
|
97
|
+
slots += ", 'coord', '__weakref__'"
|
|
98
|
+
arglist = '(self, %s, coord=None)' % args
|
|
99
|
+
else:
|
|
100
|
+
slots = "'coord', '__weakref__'"
|
|
101
|
+
arglist = '(self, coord=None)'
|
|
102
|
+
|
|
103
|
+
src += " __slots__ = (%s)\n" % slots
|
|
104
|
+
src += " def __init__%s:\n" % arglist
|
|
105
|
+
|
|
106
|
+
for name in self.all_entries + ['coord']:
|
|
107
|
+
src += " self.%s = %s\n" % (name, name)
|
|
108
|
+
|
|
109
|
+
return src
|
|
110
|
+
|
|
111
|
+
def _gen_children(self):
|
|
112
|
+
src = ' def children(self):\n'
|
|
113
|
+
|
|
114
|
+
if self.all_entries:
|
|
115
|
+
src += ' nodelist = []\n'
|
|
116
|
+
|
|
117
|
+
for child in self.child:
|
|
118
|
+
src += (
|
|
119
|
+
' if self.%(child)s is not None:' +
|
|
120
|
+
' nodelist.append(("%(child)s", self.%(child)s))\n') % (
|
|
121
|
+
dict(child=child))
|
|
122
|
+
|
|
123
|
+
for seq_child in self.seq_child:
|
|
124
|
+
src += (
|
|
125
|
+
' for i, child in enumerate(self.%(child)s or []):\n'
|
|
126
|
+
' nodelist.append(("%(child)s[%%d]" %% i, child))\n') % (
|
|
127
|
+
dict(child=seq_child))
|
|
128
|
+
|
|
129
|
+
src += ' return tuple(nodelist)\n'
|
|
130
|
+
else:
|
|
131
|
+
src += ' return ()\n'
|
|
132
|
+
|
|
133
|
+
return src
|
|
134
|
+
|
|
135
|
+
def _gen_iter(self):
|
|
136
|
+
src = ' def __iter__(self):\n'
|
|
137
|
+
|
|
138
|
+
if self.all_entries:
|
|
139
|
+
for child in self.child:
|
|
140
|
+
src += (
|
|
141
|
+
' if self.%(child)s is not None:\n' +
|
|
142
|
+
' yield self.%(child)s\n') % (dict(child=child))
|
|
143
|
+
|
|
144
|
+
for seq_child in self.seq_child:
|
|
145
|
+
src += (
|
|
146
|
+
' for child in (self.%(child)s or []):\n'
|
|
147
|
+
' yield child\n') % (dict(child=seq_child))
|
|
148
|
+
|
|
149
|
+
if not (self.child or self.seq_child):
|
|
150
|
+
# Empty generator
|
|
151
|
+
src += (
|
|
152
|
+
' return\n' +
|
|
153
|
+
' yield\n')
|
|
154
|
+
else:
|
|
155
|
+
# Empty generator
|
|
156
|
+
src += (
|
|
157
|
+
' return\n' +
|
|
158
|
+
' yield\n')
|
|
159
|
+
|
|
160
|
+
return src
|
|
161
|
+
|
|
162
|
+
def _gen_attr_names(self):
|
|
163
|
+
src = " attr_names = (" + ''.join("%r, " % nm for nm in self.attr) + ')'
|
|
164
|
+
return src
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
_PROLOGUE_COMMENT = \
|
|
168
|
+
r'''#-----------------------------------------------------------------
|
|
169
|
+
# ** ATTENTION **
|
|
170
|
+
# This code was automatically generated from the file:
|
|
171
|
+
# $cfg_filename
|
|
172
|
+
#
|
|
173
|
+
# Do not modify it directly. Modify the configuration file and
|
|
174
|
+
# run the generator again.
|
|
175
|
+
# ** ** *** ** **
|
|
176
|
+
#
|
|
177
|
+
# pycparser: c_ast.py
|
|
178
|
+
#
|
|
179
|
+
# AST Node classes.
|
|
180
|
+
#
|
|
181
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
182
|
+
# License: BSD
|
|
183
|
+
#-----------------------------------------------------------------
|
|
184
|
+
|
|
185
|
+
'''
|
|
186
|
+
|
|
187
|
+
_PROLOGUE_CODE = r'''
|
|
188
|
+
import sys
|
|
189
|
+
|
|
190
|
+
def _repr(obj):
|
|
191
|
+
"""
|
|
192
|
+
Get the representation of an object, with dedicated pprint-like format for lists.
|
|
193
|
+
"""
|
|
194
|
+
if isinstance(obj, list):
|
|
195
|
+
return '[' + (',\n '.join((_repr(e).replace('\n', '\n ') for e in obj))) + '\n]'
|
|
196
|
+
else:
|
|
197
|
+
return repr(obj)
|
|
198
|
+
|
|
199
|
+
class Node(object):
|
|
200
|
+
__slots__ = ()
|
|
201
|
+
""" Abstract base class for AST nodes.
|
|
202
|
+
"""
|
|
203
|
+
def __repr__(self):
|
|
204
|
+
""" Generates a python representation of the current node
|
|
205
|
+
"""
|
|
206
|
+
result = self.__class__.__name__ + '('
|
|
207
|
+
|
|
208
|
+
indent = ''
|
|
209
|
+
separator = ''
|
|
210
|
+
for name in self.__slots__[:-2]:
|
|
211
|
+
result += separator
|
|
212
|
+
result += indent
|
|
213
|
+
result += name + '=' + (_repr(getattr(self, name)).replace('\n', '\n ' + (' ' * (len(name) + len(self.__class__.__name__)))))
|
|
214
|
+
|
|
215
|
+
separator = ','
|
|
216
|
+
indent = '\n ' + (' ' * len(self.__class__.__name__))
|
|
217
|
+
|
|
218
|
+
result += indent + ')'
|
|
219
|
+
|
|
220
|
+
return result
|
|
221
|
+
|
|
222
|
+
def children(self):
|
|
223
|
+
""" A sequence of all children that are Nodes
|
|
224
|
+
"""
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
def show(self, buf=sys.stdout, offset=0, attrnames=False, nodenames=False, showcoord=False, _my_node_name=None):
|
|
228
|
+
""" Pretty print the Node and all its attributes and
|
|
229
|
+
children (recursively) to a buffer.
|
|
230
|
+
|
|
231
|
+
buf:
|
|
232
|
+
Open IO buffer into which the Node is printed.
|
|
233
|
+
|
|
234
|
+
offset:
|
|
235
|
+
Initial offset (amount of leading spaces)
|
|
236
|
+
|
|
237
|
+
attrnames:
|
|
238
|
+
True if you want to see the attribute names in
|
|
239
|
+
name=value pairs. False to only see the values.
|
|
240
|
+
|
|
241
|
+
nodenames:
|
|
242
|
+
True if you want to see the actual node names
|
|
243
|
+
within their parents.
|
|
244
|
+
|
|
245
|
+
showcoord:
|
|
246
|
+
Do you want the coordinates of each Node to be
|
|
247
|
+
displayed.
|
|
248
|
+
"""
|
|
249
|
+
lead = ' ' * offset
|
|
250
|
+
if nodenames and _my_node_name is not None:
|
|
251
|
+
buf.write(lead + self.__class__.__name__+ ' <' + _my_node_name + '>: ')
|
|
252
|
+
else:
|
|
253
|
+
buf.write(lead + self.__class__.__name__+ ': ')
|
|
254
|
+
|
|
255
|
+
if self.attr_names:
|
|
256
|
+
if attrnames:
|
|
257
|
+
nvlist = [(n, getattr(self,n)) for n in self.attr_names]
|
|
258
|
+
attrstr = ', '.join('%s=%s' % nv for nv in nvlist)
|
|
259
|
+
else:
|
|
260
|
+
vlist = [getattr(self, n) for n in self.attr_names]
|
|
261
|
+
attrstr = ', '.join('%s' % v for v in vlist)
|
|
262
|
+
buf.write(attrstr)
|
|
263
|
+
|
|
264
|
+
if showcoord:
|
|
265
|
+
buf.write(' (at %s)' % self.coord)
|
|
266
|
+
buf.write('\n')
|
|
267
|
+
|
|
268
|
+
for (child_name, child) in self.children():
|
|
269
|
+
child.show(
|
|
270
|
+
buf,
|
|
271
|
+
offset=offset + 2,
|
|
272
|
+
attrnames=attrnames,
|
|
273
|
+
nodenames=nodenames,
|
|
274
|
+
showcoord=showcoord,
|
|
275
|
+
_my_node_name=child_name)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class NodeVisitor(object):
|
|
279
|
+
""" A base NodeVisitor class for visiting c_ast nodes.
|
|
280
|
+
Subclass it and define your own visit_XXX methods, where
|
|
281
|
+
XXX is the class name you want to visit with these
|
|
282
|
+
methods.
|
|
283
|
+
|
|
284
|
+
For example:
|
|
285
|
+
|
|
286
|
+
class ConstantVisitor(NodeVisitor):
|
|
287
|
+
def __init__(self):
|
|
288
|
+
self.values = []
|
|
289
|
+
|
|
290
|
+
def visit_Constant(self, node):
|
|
291
|
+
self.values.append(node.value)
|
|
292
|
+
|
|
293
|
+
Creates a list of values of all the constant nodes
|
|
294
|
+
encountered below the given node. To use it:
|
|
295
|
+
|
|
296
|
+
cv = ConstantVisitor()
|
|
297
|
+
cv.visit(node)
|
|
298
|
+
|
|
299
|
+
Notes:
|
|
300
|
+
|
|
301
|
+
* generic_visit() will be called for AST nodes for which
|
|
302
|
+
no visit_XXX method was defined.
|
|
303
|
+
* The children of nodes for which a visit_XXX was
|
|
304
|
+
defined will not be visited - if you need this, call
|
|
305
|
+
generic_visit() on the node.
|
|
306
|
+
You can use:
|
|
307
|
+
NodeVisitor.generic_visit(self, node)
|
|
308
|
+
* Modeled after Python's own AST visiting facilities
|
|
309
|
+
(the ast module of Python 3.0)
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
_method_cache = None
|
|
313
|
+
|
|
314
|
+
def visit(self, node):
|
|
315
|
+
""" Visit a node.
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
if self._method_cache is None:
|
|
319
|
+
self._method_cache = {}
|
|
320
|
+
|
|
321
|
+
visitor = self._method_cache.get(node.__class__.__name__, None)
|
|
322
|
+
if visitor is None:
|
|
323
|
+
method = 'visit_' + node.__class__.__name__
|
|
324
|
+
visitor = getattr(self, method, self.generic_visit)
|
|
325
|
+
self._method_cache[node.__class__.__name__] = visitor
|
|
326
|
+
|
|
327
|
+
return visitor(node)
|
|
328
|
+
|
|
329
|
+
def generic_visit(self, node):
|
|
330
|
+
""" Called if no explicit visitor function exists for a
|
|
331
|
+
node. Implements preorder visiting of the node.
|
|
332
|
+
"""
|
|
333
|
+
for c in node:
|
|
334
|
+
self.visit(c)
|
|
335
|
+
|
|
336
|
+
'''
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#-----------------------------------------------------------------
|
|
2
|
+
# pycparser: _build_tables.py
|
|
3
|
+
#
|
|
4
|
+
# A dummy for generating the lexing/parsing tables and and
|
|
5
|
+
# compiling them into .pyc for faster execution in optimized mode.
|
|
6
|
+
# Also generates AST code from the configuration file.
|
|
7
|
+
# Should be called from the pycparser directory.
|
|
8
|
+
#
|
|
9
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
10
|
+
# License: BSD
|
|
11
|
+
#-----------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
# Insert '.' and '..' as first entries to the search path for modules.
|
|
14
|
+
# Restricted environments like embeddable python do not include the
|
|
15
|
+
# current working directory on startup.
|
|
16
|
+
import importlib
|
|
17
|
+
import sys
|
|
18
|
+
sys.path[0:0] = ['.', '..']
|
|
19
|
+
|
|
20
|
+
# Generate c_ast.py
|
|
21
|
+
from _ast_gen import ASTCodeGenerator
|
|
22
|
+
ast_gen = ASTCodeGenerator('_c_ast.cfg')
|
|
23
|
+
ast_gen.generate(open('c_ast.py', 'w'))
|
|
24
|
+
|
|
25
|
+
from pycparser import c_parser
|
|
26
|
+
|
|
27
|
+
# Generates the tables
|
|
28
|
+
#
|
|
29
|
+
c_parser.CParser(
|
|
30
|
+
lex_optimize=True,
|
|
31
|
+
yacc_debug=False,
|
|
32
|
+
yacc_optimize=True)
|
|
33
|
+
|
|
34
|
+
# Load to compile into .pyc
|
|
35
|
+
#
|
|
36
|
+
importlib.invalidate_caches()
|
|
37
|
+
|
|
38
|
+
import lextab
|
|
39
|
+
import yacctab
|
|
40
|
+
import c_ast
|
pycparser/_c_ast.cfg
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#-----------------------------------------------------------------
|
|
2
|
+
# pycparser: _c_ast.cfg
|
|
3
|
+
#
|
|
4
|
+
# Defines the AST Node classes used in pycparser.
|
|
5
|
+
#
|
|
6
|
+
# Each entry is a Node sub-class name, listing the attributes
|
|
7
|
+
# and child nodes of the class:
|
|
8
|
+
# <name>* - a child node
|
|
9
|
+
# <name>** - a sequence of child nodes
|
|
10
|
+
# <name> - an attribute
|
|
11
|
+
#
|
|
12
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
13
|
+
# License: BSD
|
|
14
|
+
#-----------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
# ArrayDecl is a nested declaration of an array with the given type.
|
|
17
|
+
# dim: the dimension (for example, constant 42)
|
|
18
|
+
# dim_quals: list of dimension qualifiers, to support C99's allowing 'const'
|
|
19
|
+
# and 'static' within the array dimension in function declarations.
|
|
20
|
+
ArrayDecl: [type*, dim*, dim_quals]
|
|
21
|
+
|
|
22
|
+
ArrayRef: [name*, subscript*]
|
|
23
|
+
|
|
24
|
+
# op: =, +=, /= etc.
|
|
25
|
+
#
|
|
26
|
+
Assignment: [op, lvalue*, rvalue*]
|
|
27
|
+
|
|
28
|
+
Alignas: [alignment*]
|
|
29
|
+
|
|
30
|
+
BinaryOp: [op, left*, right*]
|
|
31
|
+
|
|
32
|
+
Break: []
|
|
33
|
+
|
|
34
|
+
Case: [expr*, stmts**]
|
|
35
|
+
|
|
36
|
+
Cast: [to_type*, expr*]
|
|
37
|
+
|
|
38
|
+
# Compound statement in C99 is a list of block items (declarations or
|
|
39
|
+
# statements).
|
|
40
|
+
#
|
|
41
|
+
Compound: [block_items**]
|
|
42
|
+
|
|
43
|
+
# Compound literal (anonymous aggregate) for C99.
|
|
44
|
+
# (type-name) {initializer_list}
|
|
45
|
+
# type: the typename
|
|
46
|
+
# init: InitList for the initializer list
|
|
47
|
+
#
|
|
48
|
+
CompoundLiteral: [type*, init*]
|
|
49
|
+
|
|
50
|
+
# type: int, char, float, string, etc.
|
|
51
|
+
#
|
|
52
|
+
Constant: [type, value]
|
|
53
|
+
|
|
54
|
+
Continue: []
|
|
55
|
+
|
|
56
|
+
# name: the variable being declared
|
|
57
|
+
# quals: list of qualifiers (const, volatile)
|
|
58
|
+
# funcspec: list function specifiers (i.e. inline in C99)
|
|
59
|
+
# storage: list of storage specifiers (extern, register, etc.)
|
|
60
|
+
# type: declaration type (probably nested with all the modifiers)
|
|
61
|
+
# init: initialization value, or None
|
|
62
|
+
# bitsize: bit field size, or None
|
|
63
|
+
#
|
|
64
|
+
Decl: [name, quals, align, storage, funcspec, type*, init*, bitsize*]
|
|
65
|
+
|
|
66
|
+
DeclList: [decls**]
|
|
67
|
+
|
|
68
|
+
Default: [stmts**]
|
|
69
|
+
|
|
70
|
+
DoWhile: [cond*, stmt*]
|
|
71
|
+
|
|
72
|
+
# Represents the ellipsis (...) parameter in a function
|
|
73
|
+
# declaration
|
|
74
|
+
#
|
|
75
|
+
EllipsisParam: []
|
|
76
|
+
|
|
77
|
+
# An empty statement (a semicolon ';' on its own)
|
|
78
|
+
#
|
|
79
|
+
EmptyStatement: []
|
|
80
|
+
|
|
81
|
+
# Enumeration type specifier
|
|
82
|
+
# name: an optional ID
|
|
83
|
+
# values: an EnumeratorList
|
|
84
|
+
#
|
|
85
|
+
Enum: [name, values*]
|
|
86
|
+
|
|
87
|
+
# A name/value pair for enumeration values
|
|
88
|
+
#
|
|
89
|
+
Enumerator: [name, value*]
|
|
90
|
+
|
|
91
|
+
# A list of enumerators
|
|
92
|
+
#
|
|
93
|
+
EnumeratorList: [enumerators**]
|
|
94
|
+
|
|
95
|
+
# A list of expressions separated by the comma operator.
|
|
96
|
+
#
|
|
97
|
+
ExprList: [exprs**]
|
|
98
|
+
|
|
99
|
+
# This is the top of the AST, representing a single C file (a
|
|
100
|
+
# translation unit in K&R jargon). It contains a list of
|
|
101
|
+
# "external-declaration"s, which is either declarations (Decl),
|
|
102
|
+
# Typedef or function definitions (FuncDef).
|
|
103
|
+
#
|
|
104
|
+
FileAST: [ext**]
|
|
105
|
+
|
|
106
|
+
# for (init; cond; next) stmt
|
|
107
|
+
#
|
|
108
|
+
For: [init*, cond*, next*, stmt*]
|
|
109
|
+
|
|
110
|
+
# name: Id
|
|
111
|
+
# args: ExprList
|
|
112
|
+
#
|
|
113
|
+
FuncCall: [name*, args*]
|
|
114
|
+
|
|
115
|
+
# type <decl>(args)
|
|
116
|
+
#
|
|
117
|
+
FuncDecl: [args*, type*]
|
|
118
|
+
|
|
119
|
+
# Function definition: a declarator for the function name and
|
|
120
|
+
# a body, which is a compound statement.
|
|
121
|
+
# There's an optional list of parameter declarations for old
|
|
122
|
+
# K&R-style definitions
|
|
123
|
+
#
|
|
124
|
+
FuncDef: [decl*, param_decls**, body*]
|
|
125
|
+
|
|
126
|
+
Goto: [name]
|
|
127
|
+
|
|
128
|
+
ID: [name]
|
|
129
|
+
|
|
130
|
+
# Holder for types that are a simple identifier (e.g. the built
|
|
131
|
+
# ins void, char etc. and typedef-defined types)
|
|
132
|
+
#
|
|
133
|
+
IdentifierType: [names]
|
|
134
|
+
|
|
135
|
+
If: [cond*, iftrue*, iffalse*]
|
|
136
|
+
|
|
137
|
+
# An initialization list used for compound literals.
|
|
138
|
+
#
|
|
139
|
+
InitList: [exprs**]
|
|
140
|
+
|
|
141
|
+
Label: [name, stmt*]
|
|
142
|
+
|
|
143
|
+
# A named initializer for C99.
|
|
144
|
+
# The name of a NamedInitializer is a sequence of Nodes, because
|
|
145
|
+
# names can be hierarchical and contain constant expressions.
|
|
146
|
+
#
|
|
147
|
+
NamedInitializer: [name**, expr*]
|
|
148
|
+
|
|
149
|
+
# a list of comma separated function parameter declarations
|
|
150
|
+
#
|
|
151
|
+
ParamList: [params**]
|
|
152
|
+
|
|
153
|
+
PtrDecl: [quals, type*]
|
|
154
|
+
|
|
155
|
+
Return: [expr*]
|
|
156
|
+
|
|
157
|
+
StaticAssert: [cond*, message*]
|
|
158
|
+
|
|
159
|
+
# name: struct tag name
|
|
160
|
+
# decls: declaration of members
|
|
161
|
+
#
|
|
162
|
+
Struct: [name, decls**]
|
|
163
|
+
|
|
164
|
+
# type: . or ->
|
|
165
|
+
# name.field or name->field
|
|
166
|
+
#
|
|
167
|
+
StructRef: [name*, type, field*]
|
|
168
|
+
|
|
169
|
+
Switch: [cond*, stmt*]
|
|
170
|
+
|
|
171
|
+
# cond ? iftrue : iffalse
|
|
172
|
+
#
|
|
173
|
+
TernaryOp: [cond*, iftrue*, iffalse*]
|
|
174
|
+
|
|
175
|
+
# A base type declaration
|
|
176
|
+
#
|
|
177
|
+
TypeDecl: [declname, quals, align, type*]
|
|
178
|
+
|
|
179
|
+
# A typedef declaration.
|
|
180
|
+
# Very similar to Decl, but without some attributes
|
|
181
|
+
#
|
|
182
|
+
Typedef: [name, quals, storage, type*]
|
|
183
|
+
|
|
184
|
+
Typename: [name, quals, align, type*]
|
|
185
|
+
|
|
186
|
+
UnaryOp: [op, expr*]
|
|
187
|
+
|
|
188
|
+
# name: union tag name
|
|
189
|
+
# decls: declaration of members
|
|
190
|
+
#
|
|
191
|
+
Union: [name, decls**]
|
|
192
|
+
|
|
193
|
+
While: [cond*, stmt*]
|
|
194
|
+
|
|
195
|
+
Pragma: [string]
|