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/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)