python-cc 0.0.2__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.
- pcc/__init__.py +0 -0
- pcc/__main__.py +3 -0
- pcc/ast/__init__.py +0 -0
- pcc/ast/ast.py +179 -0
- pcc/ast/ast_transforms.py +106 -0
- pcc/ast/c_ast.py +800 -0
- pcc/codegen/__init__.py +0 -0
- pcc/codegen/c_codegen.py +4177 -0
- pcc/evaluater/__init__.py +0 -0
- pcc/evaluater/c_evaluator.py +238 -0
- pcc/generator/__init__.py +0 -0
- pcc/generator/c_generator.py +399 -0
- pcc/lex/__init__.py +0 -0
- pcc/lex/c_lexer.py +495 -0
- pcc/lex/lexer.py +68 -0
- pcc/lex/token.py +24 -0
- pcc/parse/__init__.py +0 -0
- pcc/parse/c_parser.py +1700 -0
- pcc/parse/file_parser.py +82 -0
- pcc/parse/parser.py +300 -0
- pcc/parse/plyparser.py +56 -0
- pcc/pcc.py +38 -0
- pcc/ply/__init__.py +5 -0
- pcc/ply/cpp.py +908 -0
- pcc/ply/ctokens.py +133 -0
- pcc/ply/lex.py +1097 -0
- pcc/ply/yacc.py +3471 -0
- pcc/ply/ygen.py +74 -0
- pcc/preprocessor.py +509 -0
- pcc/project.py +78 -0
- pcc/util.py +121 -0
- python_cc-0.0.2.dist-info/METADATA +182 -0
- python_cc-0.0.2.dist-info/RECORD +36 -0
- python_cc-0.0.2.dist-info/WHEEL +4 -0
- python_cc-0.0.2.dist-info/entry_points.txt +2 -0
- python_cc-0.0.2.dist-info/licenses/LICENSE +25 -0
pcc/__init__.py
ADDED
|
File without changes
|
pcc/__main__.py
ADDED
pcc/ast/__init__.py
ADDED
|
File without changes
|
pcc/ast/ast.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
|
|
2
|
+
# AST hierarchy
|
|
3
|
+
class ASTNode(object):
|
|
4
|
+
def dump(self, indent=0):
|
|
5
|
+
raise NotImplementedError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ExprAST(ASTNode):
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NumberExprAST(ExprAST):
|
|
13
|
+
def __init__(self, val):
|
|
14
|
+
self.val = val
|
|
15
|
+
|
|
16
|
+
def dump(self, indent=0):
|
|
17
|
+
return '{0}{1}[{2}]'.format(
|
|
18
|
+
' ' * indent, self.__class__.__name__, self.val)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class VariableExprAST(ExprAST):
|
|
22
|
+
def __init__(self, name):
|
|
23
|
+
self.name = name
|
|
24
|
+
|
|
25
|
+
def dump(self, indent=0):
|
|
26
|
+
return '{0}{1}[{2}]'.format(
|
|
27
|
+
' ' * indent, self.__class__.__name__, self.name)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class VarExprAST(ExprAST):
|
|
31
|
+
def __init__(self, vars, body):
|
|
32
|
+
# vars is a sequence of (name, init) pairs
|
|
33
|
+
self.vars = vars
|
|
34
|
+
self.body = body
|
|
35
|
+
|
|
36
|
+
def dump(self, indent=0):
|
|
37
|
+
prefix = ' ' * indent
|
|
38
|
+
s = '{0}{1}\n'.format(prefix, self.__class__.__name__)
|
|
39
|
+
for name, init in self.vars:
|
|
40
|
+
s += '{0} {1}'.format(prefix, name)
|
|
41
|
+
if init is None:
|
|
42
|
+
s += '\n'
|
|
43
|
+
else:
|
|
44
|
+
s += '=\n' + init.dump(indent+2) + '\n'
|
|
45
|
+
s += '{0} Body:\n'.format(prefix)
|
|
46
|
+
s += self.body.dump(indent + 2)
|
|
47
|
+
return s
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class UnaryExprAST(ExprAST):
|
|
51
|
+
def __init__(self, op, operand):
|
|
52
|
+
self.op = op
|
|
53
|
+
self.operand = operand
|
|
54
|
+
|
|
55
|
+
def dump(self, indent=0):
|
|
56
|
+
s = '{0}{1}[{2}]\n'.format(
|
|
57
|
+
' ' * indent, self.__class__.__name__, self.op)
|
|
58
|
+
s += self.operand.dump(indent + 2)
|
|
59
|
+
return s
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class BinaryExprAST(ExprAST):
|
|
63
|
+
def __init__(self, op, lhs, rhs):
|
|
64
|
+
self.op = op
|
|
65
|
+
self.lhs = lhs
|
|
66
|
+
self.rhs = rhs
|
|
67
|
+
|
|
68
|
+
def dump(self, indent=0):
|
|
69
|
+
s = '{0}{1}[{2}]\n'.format(
|
|
70
|
+
' ' * indent, self.__class__.__name__, self.op)
|
|
71
|
+
s += self.lhs.dump(indent + 2) + '\n'
|
|
72
|
+
s += self.rhs.dump(indent + 2)
|
|
73
|
+
return s
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class IfExprAST(ExprAST):
|
|
77
|
+
def __init__(self, cond_expr, then_expr, else_expr):
|
|
78
|
+
self.cond_expr = cond_expr
|
|
79
|
+
self.then_expr = then_expr
|
|
80
|
+
self.else_expr = else_expr
|
|
81
|
+
|
|
82
|
+
def dump(self, indent=0):
|
|
83
|
+
prefix = ' ' * indent
|
|
84
|
+
s = '{0}{1}\n'.format(prefix, self.__class__.__name__)
|
|
85
|
+
s += '{0} Condition:\n{1}\n'.format(
|
|
86
|
+
prefix, self.cond_expr.dump(indent + 2))
|
|
87
|
+
s += '{0} Then:\n{1}\n'.format(
|
|
88
|
+
prefix, self.then_expr.dump(indent + 2))
|
|
89
|
+
s += '{0} Else:\n{1}'.format(
|
|
90
|
+
prefix, self.else_expr.dump(indent + 2))
|
|
91
|
+
return s
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ForExprAST(ExprAST):
|
|
95
|
+
def __init__(self, id_name, start_expr, end_expr, step_expr, body):
|
|
96
|
+
self.id_name = id_name
|
|
97
|
+
self.start_expr = start_expr
|
|
98
|
+
self.end_expr = end_expr
|
|
99
|
+
self.step_expr = step_expr
|
|
100
|
+
self.body = body
|
|
101
|
+
|
|
102
|
+
def dump(self, indent=0):
|
|
103
|
+
prefix = ' ' * indent
|
|
104
|
+
s = '{0}{1}\n'.format(prefix, self.__class__.__name__)
|
|
105
|
+
s += '{0} Start [{1}]:\n{2}\n'.format(
|
|
106
|
+
prefix, self.id_name, self.start_expr.dump(indent + 2))
|
|
107
|
+
s += '{0} End:\n{1}\n'.format(
|
|
108
|
+
prefix, self.end_expr.dump(indent + 2))
|
|
109
|
+
s += '{0} Step:\n{1}\n'.format(
|
|
110
|
+
prefix, self.step_expr.dump(indent + 2))
|
|
111
|
+
s += '{0} Body:\n{1}\n'.format(
|
|
112
|
+
prefix, self.body.dump(indent + 2))
|
|
113
|
+
return s
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class CallExprAST(ExprAST):
|
|
117
|
+
def __init__(self, callee, args):
|
|
118
|
+
self.callee = callee
|
|
119
|
+
self.args = args
|
|
120
|
+
|
|
121
|
+
def dump(self, indent=0):
|
|
122
|
+
s = '{0}{1}[{2}]\n'.format(
|
|
123
|
+
' ' * indent, self.__class__.__name__, self.callee)
|
|
124
|
+
for arg in self.args:
|
|
125
|
+
s += arg.dump(indent + 2) + '\n'
|
|
126
|
+
return s[:-1] # snip out trailing '\n'
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class PrototypeAST(ASTNode):
|
|
130
|
+
def __init__(self, name, argnames, isoperator=False, prec=0):
|
|
131
|
+
self.name = name
|
|
132
|
+
self.argnames = argnames
|
|
133
|
+
self.isoperator = isoperator
|
|
134
|
+
self.prec = prec
|
|
135
|
+
|
|
136
|
+
def is_unary_op(self):
|
|
137
|
+
return self.isoperator and len(self.argnames) == 1
|
|
138
|
+
|
|
139
|
+
def is_binary_op(self):
|
|
140
|
+
return self.isoperator and len(self.argnames) == 2
|
|
141
|
+
|
|
142
|
+
def get_op_name(self):
|
|
143
|
+
assert self.isoperator
|
|
144
|
+
return self.name[-1]
|
|
145
|
+
|
|
146
|
+
def dump(self, indent=0):
|
|
147
|
+
s = '{0}{1} {2}({3})'.format(
|
|
148
|
+
' ' * indent, self.__class__.__name__, self.name,
|
|
149
|
+
', '.join(self.argnames))
|
|
150
|
+
if self.isoperator:
|
|
151
|
+
s += '[operator with prec={0}]'.format(self.prec)
|
|
152
|
+
return s
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class FunctionAST(ASTNode):
|
|
156
|
+
def __init__(self, proto, body):
|
|
157
|
+
self.proto = proto
|
|
158
|
+
self.body = body
|
|
159
|
+
|
|
160
|
+
_anonymous_function_counter = 0
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def create_anonymous(klass, expr):
|
|
164
|
+
"""Create an anonymous function to hold an expression."""
|
|
165
|
+
klass._anonymous_function_counter += 1
|
|
166
|
+
return klass(
|
|
167
|
+
PrototypeAST('_anon{0}'.format(klass._anonymous_function_counter),
|
|
168
|
+
[]),
|
|
169
|
+
expr)
|
|
170
|
+
|
|
171
|
+
def is_anonymous(self):
|
|
172
|
+
return self.proto.name.startswith('_anon')
|
|
173
|
+
|
|
174
|
+
def dump(self, indent=0):
|
|
175
|
+
s = '{0}{1}[{2}]\n'.format(
|
|
176
|
+
' ' * indent, self.__class__.__name__, self.proto.dump())
|
|
177
|
+
s += self.body.dump(indent + 2) + '\n'
|
|
178
|
+
return s
|
|
179
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#------------------------------------------------------------------------------
|
|
2
|
+
# pycparser: ast_transforms.py
|
|
3
|
+
#
|
|
4
|
+
# Some utilities used by the parser to create a friendlier AST.
|
|
5
|
+
#
|
|
6
|
+
# Copyright (C) 2008-2015, Eli Bendersky
|
|
7
|
+
# License: BSD
|
|
8
|
+
#------------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
from . import c_ast
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fix_switch_cases(switch_node):
|
|
14
|
+
""" The 'case' statements in a 'switch' come out of parsing with one
|
|
15
|
+
child node, so subsequent statements are just tucked to the parent
|
|
16
|
+
Compound. Additionally, consecutive (fall-through) case statements
|
|
17
|
+
come out messy. This is a peculiarity of the C grammar. The following:
|
|
18
|
+
|
|
19
|
+
switch (myvar) {
|
|
20
|
+
case 10:
|
|
21
|
+
k = 10;
|
|
22
|
+
p = k + 1;
|
|
23
|
+
return 10;
|
|
24
|
+
case 20:
|
|
25
|
+
case 30:
|
|
26
|
+
return 20;
|
|
27
|
+
default:
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Creates this tree (pseudo-dump):
|
|
32
|
+
|
|
33
|
+
Switch
|
|
34
|
+
ID: myvar
|
|
35
|
+
Compound:
|
|
36
|
+
Case 10:
|
|
37
|
+
k = 10
|
|
38
|
+
p = k + 1
|
|
39
|
+
return 10
|
|
40
|
+
Case 20:
|
|
41
|
+
Case 30:
|
|
42
|
+
return 20
|
|
43
|
+
Default:
|
|
44
|
+
break
|
|
45
|
+
|
|
46
|
+
The goal of this transform it to fix this mess, turning it into the
|
|
47
|
+
following:
|
|
48
|
+
|
|
49
|
+
Switch
|
|
50
|
+
ID: myvar
|
|
51
|
+
Compound:
|
|
52
|
+
Case 10:
|
|
53
|
+
k = 10
|
|
54
|
+
p = k + 1
|
|
55
|
+
return 10
|
|
56
|
+
Case 20:
|
|
57
|
+
Case 30:
|
|
58
|
+
return 20
|
|
59
|
+
Default:
|
|
60
|
+
break
|
|
61
|
+
|
|
62
|
+
A fixed AST node is returned. The argument may be modified.
|
|
63
|
+
"""
|
|
64
|
+
assert isinstance(switch_node, c_ast.Switch)
|
|
65
|
+
if not isinstance(switch_node.stmt, c_ast.Compound):
|
|
66
|
+
return switch_node
|
|
67
|
+
|
|
68
|
+
# The new Compound child for the Switch, which will collect children in the
|
|
69
|
+
# correct order
|
|
70
|
+
new_compound = c_ast.Compound([], switch_node.stmt.coord)
|
|
71
|
+
|
|
72
|
+
# The last Case/Default node
|
|
73
|
+
last_case = None
|
|
74
|
+
|
|
75
|
+
# Goes over the children of the Compound below the Switch, adding them
|
|
76
|
+
# either directly below new_compound or below the last Case as appropriate
|
|
77
|
+
for child in switch_node.stmt.block_items:
|
|
78
|
+
if isinstance(child, (c_ast.Case, c_ast.Default)):
|
|
79
|
+
# If it's a Case/Default:
|
|
80
|
+
# 1. Add it to the Compound and mark as "last case"
|
|
81
|
+
# 2. If its immediate child is also a Case or Default, promote it
|
|
82
|
+
# to a sibling.
|
|
83
|
+
new_compound.block_items.append(child)
|
|
84
|
+
_extract_nested_case(child, new_compound.block_items)
|
|
85
|
+
last_case = new_compound.block_items[-1]
|
|
86
|
+
else:
|
|
87
|
+
# Other statements are added as children to the last case, if it
|
|
88
|
+
# exists.
|
|
89
|
+
if last_case is None:
|
|
90
|
+
new_compound.block_items.append(child)
|
|
91
|
+
else:
|
|
92
|
+
last_case.stmts.append(child)
|
|
93
|
+
|
|
94
|
+
switch_node.stmt = new_compound
|
|
95
|
+
return switch_node
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _extract_nested_case(case_node, stmts_list):
|
|
99
|
+
""" Recursively extract consecutive Case statements that are made nested
|
|
100
|
+
by the parser and add them to the stmts_list.
|
|
101
|
+
"""
|
|
102
|
+
if isinstance(case_node.stmts[0], (c_ast.Case, c_ast.Default)):
|
|
103
|
+
stmts_list.append(case_node.stmts.pop())
|
|
104
|
+
_extract_nested_case(stmts_list[-1], stmts_list)
|
|
105
|
+
|
|
106
|
+
|