6 python stutter.py stutter_code.stt > c_code.c
14 def is_integer(s_expression):
15 return isinstance(s_expression, int) \
16 and not s_expression is True \
17 and not s_expression is False
19 # String to s-expressions
21 TOKEN = re.compile(r'\s*({})'.format('|'.join('(?P<{}>{})'.format(*token) for token in [
22 ('open_parenthese', r'\('),
23 ('close_parenthese', r'\)'),
24 ('integer_literal', r'\d+'),
25 ('unexpected_character', r'.'),
28 def parse_all(source):
32 for token in TOKEN.finditer(source):
33 if token.group('open_parenthese'):
37 elif token.group('close_parenthese'):
39 raise Exception('Parenthese closed but not opened')
41 stack[-1].append(tuple(items))
44 elif token.group('integer_literal'):
45 items.append(int(token.group('integer_literal')))
47 elif token.group('unexpected_character'):
48 raise Exception('Unexpected character {}'.format(
49 token.group('unexpected_character'),
57 raise Exception('Parenthese opened but not closed')
64 def __init__(self, name):
67 class CPointerType(CType):
68 def __init__(self, pointer_to):
69 self.pointer_to = pointer_to
71 class CArgumentDeclaration(object):
72 def __init__(self, type, name):
73 assert isinstance(type, CType)
77 class CExpression(object):
80 class CIntegerLiteralExpression(CExpression):
81 def __init__(self, integer):
82 assert isinstance(integer, int)
84 # Booleans in Python are integers but we don't want them
85 assert not integer is True
86 assert not integer is False
88 self.integer = integer
90 class CFunctionCallExpression(CExpression):
91 def __init__(self, name, arguments):
92 assert all(isinstance(argument, CExpression) for argument in arguments)
94 self.arguments = arguments
96 class CStatement(object):
99 class CExpressionStatement(CStatement):
100 def __init__(self, expression):
101 self.expression = expression
103 class CReturnStatement(CStatement):
104 def __init__(self, expression):
105 self.expression = expression
107 class CFunctionDeclaration(object):
108 def __init__(self, return_type, name, argument_declaration_list, body):
109 assert isinstance(return_type, CType)
110 assert isinstance(argument_declaration_list, list)
111 assert all(isinstance(ad, CArgumentDeclaration) for ad in argument_declaration_list)
112 assert isinstance(body, list)
113 assert all(isinstance(s, CStatement) for s in body)
115 self.return_type = return_type
117 self.argument_declaration_list = argument_declaration_list
120 # BEGIN S-expression to C AST layer
122 def evaluate_to_c(s_expression):
123 if is_integer(s_expression):
124 return CIntegerLiteralExpression(s_expression)
126 raise Exception('Unable to evaluate expression {} to C'.format(s_expression))
128 def evaluate_all_to_c(s_expressions):
129 c_expressions = list(map(evaluate_to_c, s_expressions))
130 body = list(map(CExpressionStatement, c_expressions[:-1])) + [CReturnStatement(c_expressions[-1])]
132 return CFunctionDeclaration(
136 CArgumentDeclaration(CType('int'), 'argc'),
137 CArgumentDeclaration(CPointerType(CPointerType(CType('char'))), 'argv'),
142 # BEGIN C AST to C source layer
147 assert isinstance(string, str)
149 def indent_line(line):
155 return ' ' * TAB_WIDTH + line
157 return '\n'.join(indent_line(line) for line in string.splitlines())
159 def generate_pointer_type(pointer_type):
160 assert isinstance(pointer_type, CPointerType)
161 return '{}*'.format(generate_type(pointer_type.pointer_to))
165 generate_pointer_type = generate_pointer_type):
166 assert isinstance(type, CType)
168 if isinstance(type, CPointerType):
169 return generate_pointer_type(type)
173 def generate_argument_declaration(argument_declaration):
174 assert isinstance(argument_declaration, CArgumentDeclaration)
175 return '{} {}'.format(generate_type(argument_declaration.type), argument_declaration.name)
177 def generate_argument_declaration_list(argument_declarations):
178 return ', '.join(generate_argument_declaration(ad) for ad in argument_declarations)
180 def generate_integer_literal_expression(expression):
181 assert isinstance(expression, CIntegerLiteralExpression)
182 return str(expression.integer)
184 def generate_function_call_expression(expression):
185 assert isinstance(expression, CFunctionCallExpression)
186 return '{}({})'.format(
188 ', '.join(generate_expression(e) for e in expression.arguments),
191 def generate_expression(
193 generate_integer_literal_expression = generate_integer_literal_expression,
194 generate_function_call_expression = generate_function_call_expression,
197 if isinstance(expression, CIntegerLiteralExpression):
198 return generate_integer_literal_expression(expression)
200 if isinstance(expression, CFunctionCallExpression):
201 return generate_function_call_expression(expression)
203 raise Exception('Expression type {} not implemented'.format(type(expression)))
205 def generate_expression_statement(statement):
206 return '{};'.format(generate_expression(statement.expression))
208 def generate_return_statement(statement):
209 return 'return {};'.format(generate_expression(statement.expression))
211 def generate_statement(
213 generate_expression_statement = generate_expression_statement,
214 generate_return_statement = generate_return_statement):
216 if isinstance(statement, CExpressionStatement):
217 return generate_expression_statement(statement)
219 if isinstance(statement, CReturnStatement):
220 return generate_return_statement(statement)
222 raise Exception('Handling for statements of type {} not implemented'.format(type(statement.type)))
224 def generate_statement_list(statements):
225 assert all(isinstance(s, CStatement) for s in statements)
226 return '\n'.join(generate_statement(s) for s in statements)
228 FUNCTION_DEFINITION_TEMPLATE = string.Template(
230 $return_type $name($argument_declaration_list)
236 def generate_function_declaration(function_declaration):
237 assert isinstance(function_declaration, CFunctionDeclaration)
238 return FUNCTION_DEFINITION_TEMPLATE.substitute(
239 return_type = generate_type(function_declaration.return_type),
240 name = function_declaration.name,
241 argument_declaration_list = generate_argument_declaration_list(function_declaration.argument_declaration_list),
242 body = indent(generate_statement_list(function_declaration.body)),
245 if __name__ == '__main__':
247 source_file_name = sys.argv[1]
249 with open(source_file_name, 'r') as source_file:
250 source = source_file.read()
252 result = generate_function_declaration(evaluate_all_to_c(parse_all(source)))