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/ply/ygen.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# ply: ygen.py
|
|
2
|
+
#
|
|
3
|
+
# This is a support program that auto-generates different versions of the YACC parsing
|
|
4
|
+
# function with different features removed for the purposes of performance.
|
|
5
|
+
#
|
|
6
|
+
# Users should edit the method LParser.parsedebug() in yacc.py. The source code
|
|
7
|
+
# for that method is then used to create the other methods. See the comments in
|
|
8
|
+
# yacc.py for further details.
|
|
9
|
+
|
|
10
|
+
import os.path
|
|
11
|
+
import shutil
|
|
12
|
+
|
|
13
|
+
def get_source_range(lines, tag):
|
|
14
|
+
srclines = enumerate(lines)
|
|
15
|
+
start_tag = '#--! %s-start' % tag
|
|
16
|
+
end_tag = '#--! %s-end' % tag
|
|
17
|
+
|
|
18
|
+
for start_index, line in srclines:
|
|
19
|
+
if line.strip().startswith(start_tag):
|
|
20
|
+
break
|
|
21
|
+
|
|
22
|
+
for end_index, line in srclines:
|
|
23
|
+
if line.strip().endswith(end_tag):
|
|
24
|
+
break
|
|
25
|
+
|
|
26
|
+
return (start_index + 1, end_index)
|
|
27
|
+
|
|
28
|
+
def filter_section(lines, tag):
|
|
29
|
+
filtered_lines = []
|
|
30
|
+
include = True
|
|
31
|
+
tag_text = '#--! %s' % tag
|
|
32
|
+
for line in lines:
|
|
33
|
+
if line.strip().startswith(tag_text):
|
|
34
|
+
include = not include
|
|
35
|
+
elif include:
|
|
36
|
+
filtered_lines.append(line)
|
|
37
|
+
return filtered_lines
|
|
38
|
+
|
|
39
|
+
def main():
|
|
40
|
+
dirname = os.path.dirname(__file__)
|
|
41
|
+
shutil.copy2(os.path.join(dirname, 'yacc.py'), os.path.join(dirname, 'yacc.py.bak'))
|
|
42
|
+
with open(os.path.join(dirname, 'yacc.py'), 'r') as f:
|
|
43
|
+
lines = f.readlines()
|
|
44
|
+
|
|
45
|
+
parse_start, parse_end = get_source_range(lines, 'parsedebug')
|
|
46
|
+
parseopt_start, parseopt_end = get_source_range(lines, 'parseopt')
|
|
47
|
+
parseopt_notrack_start, parseopt_notrack_end = get_source_range(lines, 'parseopt-notrack')
|
|
48
|
+
|
|
49
|
+
# Get the original source
|
|
50
|
+
orig_lines = lines[parse_start:parse_end]
|
|
51
|
+
|
|
52
|
+
# Filter the DEBUG sections out
|
|
53
|
+
parseopt_lines = filter_section(orig_lines, 'DEBUG')
|
|
54
|
+
|
|
55
|
+
# Filter the TRACKING sections out
|
|
56
|
+
parseopt_notrack_lines = filter_section(parseopt_lines, 'TRACKING')
|
|
57
|
+
|
|
58
|
+
# Replace the parser source sections with updated versions
|
|
59
|
+
lines[parseopt_notrack_start:parseopt_notrack_end] = parseopt_notrack_lines
|
|
60
|
+
lines[parseopt_start:parseopt_end] = parseopt_lines
|
|
61
|
+
|
|
62
|
+
lines = [line.rstrip()+'\n' for line in lines]
|
|
63
|
+
with open(os.path.join(dirname, 'yacc.py'), 'w') as f:
|
|
64
|
+
f.writelines(lines)
|
|
65
|
+
|
|
66
|
+
print('Updated yacc.py')
|
|
67
|
+
|
|
68
|
+
if __name__ == '__main__':
|
|
69
|
+
main()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
pycparser/plyparser.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#-----------------------------------------------------------------
|
|
2
|
+
# plyparser.py
|
|
3
|
+
#
|
|
4
|
+
# PLYParser class and other utilities for simplifying programming
|
|
5
|
+
# parsers with PLY
|
|
6
|
+
#
|
|
7
|
+
# Eli Bendersky [https://eli.thegreenplace.net/]
|
|
8
|
+
# License: BSD
|
|
9
|
+
#-----------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
import warnings
|
|
12
|
+
|
|
13
|
+
class Coord(object):
|
|
14
|
+
""" Coordinates of a syntactic element. Consists of:
|
|
15
|
+
- File name
|
|
16
|
+
- Line number
|
|
17
|
+
- (optional) column number, for the Lexer
|
|
18
|
+
"""
|
|
19
|
+
__slots__ = ('file', 'line', 'column', '__weakref__')
|
|
20
|
+
def __init__(self, file, line, column=None):
|
|
21
|
+
self.file = file
|
|
22
|
+
self.line = line
|
|
23
|
+
self.column = column
|
|
24
|
+
|
|
25
|
+
def __str__(self):
|
|
26
|
+
str = "%s:%s" % (self.file, self.line)
|
|
27
|
+
if self.column: str += ":%s" % self.column
|
|
28
|
+
return str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ParseError(Exception): pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class PLYParser(object):
|
|
35
|
+
def _create_opt_rule(self, rulename):
|
|
36
|
+
""" Given a rule name, creates an optional ply.yacc rule
|
|
37
|
+
for it. The name of the optional rule is
|
|
38
|
+
<rulename>_opt
|
|
39
|
+
"""
|
|
40
|
+
optname = rulename + '_opt'
|
|
41
|
+
|
|
42
|
+
def optrule(self, p):
|
|
43
|
+
p[0] = p[1]
|
|
44
|
+
|
|
45
|
+
optrule.__doc__ = '%s : empty\n| %s' % (optname, rulename)
|
|
46
|
+
optrule.__name__ = 'p_%s' % optname
|
|
47
|
+
setattr(self.__class__, optrule.__name__, optrule)
|
|
48
|
+
|
|
49
|
+
def _coord(self, lineno, column=None):
|
|
50
|
+
return Coord(
|
|
51
|
+
file=self.clex.filename,
|
|
52
|
+
line=lineno,
|
|
53
|
+
column=column)
|
|
54
|
+
|
|
55
|
+
def _token_coord(self, p, token_idx):
|
|
56
|
+
""" Returns the coordinates for the YaccProduction object 'p' indexed
|
|
57
|
+
with 'token_idx'. The coordinate includes the 'lineno' and
|
|
58
|
+
'column'. Both follow the lex semantic, starting from 1.
|
|
59
|
+
"""
|
|
60
|
+
last_cr = p.lexer.lexer.lexdata.rfind('\n', 0, p.lexpos(token_idx))
|
|
61
|
+
if last_cr < 0:
|
|
62
|
+
last_cr = -1
|
|
63
|
+
column = (p.lexpos(token_idx) - (last_cr))
|
|
64
|
+
return self._coord(p.lineno(token_idx), column)
|
|
65
|
+
|
|
66
|
+
def _parse_error(self, msg, coord):
|
|
67
|
+
raise ParseError("%s: %s" % (coord, msg))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def parameterized(*params):
|
|
71
|
+
""" Decorator to create parameterized rules.
|
|
72
|
+
|
|
73
|
+
Parameterized rule methods must be named starting with 'p_' and contain
|
|
74
|
+
'xxx', and their docstrings may contain 'xxx' and 'yyy'. These will be
|
|
75
|
+
replaced by the given parameter tuples. For example, ``p_xxx_rule()`` with
|
|
76
|
+
docstring 'xxx_rule : yyy' when decorated with
|
|
77
|
+
``@parameterized(('id', 'ID'))`` produces ``p_id_rule()`` with the docstring
|
|
78
|
+
'id_rule : ID'. Using multiple tuples produces multiple rules.
|
|
79
|
+
"""
|
|
80
|
+
def decorate(rule_func):
|
|
81
|
+
rule_func._params = params
|
|
82
|
+
return rule_func
|
|
83
|
+
return decorate
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def template(cls):
|
|
87
|
+
""" Class decorator to generate rules from parameterized rule templates.
|
|
88
|
+
|
|
89
|
+
See `parameterized` for more information on parameterized rules.
|
|
90
|
+
"""
|
|
91
|
+
issued_nodoc_warning = False
|
|
92
|
+
for attr_name in dir(cls):
|
|
93
|
+
if attr_name.startswith('p_'):
|
|
94
|
+
method = getattr(cls, attr_name)
|
|
95
|
+
if hasattr(method, '_params'):
|
|
96
|
+
# Remove the template method
|
|
97
|
+
delattr(cls, attr_name)
|
|
98
|
+
# Create parameterized rules from this method; only run this if
|
|
99
|
+
# the method has a docstring. This is to address an issue when
|
|
100
|
+
# pycparser's users are installed in -OO mode which strips
|
|
101
|
+
# docstrings away.
|
|
102
|
+
# See: https://github.com/eliben/pycparser/pull/198/ and
|
|
103
|
+
# https://github.com/eliben/pycparser/issues/197
|
|
104
|
+
# for discussion.
|
|
105
|
+
if method.__doc__ is not None:
|
|
106
|
+
_create_param_rules(cls, method)
|
|
107
|
+
elif not issued_nodoc_warning:
|
|
108
|
+
warnings.warn(
|
|
109
|
+
'parsing methods must have __doc__ for pycparser to work properly',
|
|
110
|
+
RuntimeWarning,
|
|
111
|
+
stacklevel=2)
|
|
112
|
+
issued_nodoc_warning = True
|
|
113
|
+
return cls
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _create_param_rules(cls, func):
|
|
117
|
+
""" Create ply.yacc rules based on a parameterized rule function
|
|
118
|
+
|
|
119
|
+
Generates new methods (one per each pair of parameters) based on the
|
|
120
|
+
template rule function `func`, and attaches them to `cls`. The rule
|
|
121
|
+
function's parameters must be accessible via its `_params` attribute.
|
|
122
|
+
"""
|
|
123
|
+
for xxx, yyy in func._params:
|
|
124
|
+
# Use the template method's body for each new method
|
|
125
|
+
def param_rule(self, p):
|
|
126
|
+
func(self, p)
|
|
127
|
+
|
|
128
|
+
# Substitute in the params for the grammar rule and function name
|
|
129
|
+
param_rule.__doc__ = func.__doc__.replace('xxx', xxx).replace('yyy', yyy)
|
|
130
|
+
param_rule.__name__ = func.__name__.replace('xxx', xxx)
|
|
131
|
+
|
|
132
|
+
# Attach the new method to the class
|
|
133
|
+
setattr(cls, param_rule.__name__, param_rule)
|