3 def _or_parser(*parsers):
4 def result_parser(index, tokens):
5 failure = (False, index, None)
8 success, index, value = parser(index, tokens)
11 return (success, index, value)
17 def _zero_or_more_parser(formatter, parser):
18 def result_parser(index, tokens):
21 while index < len(tokens):
22 success, index, value = parser(index, tokens)
29 return (True, index, formatter(values))
33 FurIntegerLiteralExpression = collections.namedtuple(
34 'FurIntegerLiteralExpression',
40 FurStringLiteralExpression = collections.namedtuple(
41 'FurStringLiteralExpression',
47 FurNegationExpression = collections.namedtuple(
48 'FurNegationExpression',
54 FurAdditionExpression = collections.namedtuple(
55 'FurAdditionExpression',
62 FurSubtractionExpression = collections.namedtuple(
63 'FurSubtractionExpression',
70 FurMultiplicationExpression = collections.namedtuple(
71 'FurMultiplicationExpression',
78 FurIntegerDivisionExpression = collections.namedtuple(
79 'FurIntegerDivisionExpression',
86 FurModularDivisionExpression = collections.namedtuple(
87 'FurModularDivisionExpression',
94 def _integer_literal_expression_parser(index, tokens):
95 failure = (False, index, None)
97 if tokens[index].type != 'integer_literal':
99 value = int(tokens[index].match)
102 return True, index, FurIntegerLiteralExpression(value=value)
104 def _string_literal_expression_parser(index, tokens):
105 failure = (False, index, None)
107 if tokens[index].type != 'single_quoted_string_literal':
109 value = tokens[index].match[1:-1]
112 return True, index, FurStringLiteralExpression(value=value)
114 def _negation_expression_parser(index, tokens):
115 failure = (False, index, None)
117 if tokens[index].match != '-':
120 success, index, value = _literal_level_expression_parser(index + 1, tokens)
125 return (True, index, FurNegationExpression(value=value))
127 def _literal_level_expression_parser(index, tokens):
129 _negation_expression_parser,
130 _function_call_expression_parser,
131 _integer_literal_expression_parser,
132 _string_literal_expression_parser,
135 def _multiplication_level_expression_parser(index, tokens):
136 failure = (False, index, None)
138 success, index, result = _literal_level_expression_parser(index, tokens)
143 while success and index < len(tokens) and tokens[index].type == 'multiplication_level_operator':
146 if index + 1 < len(tokens):
147 success, try_index, value = _literal_level_expression_parser(index + 1, tokens)
151 '*': FurMultiplicationExpression,
152 '//': FurIntegerDivisionExpression,
153 '%': FurModularDivisionExpression,
154 }[tokens[index].match](left=result, right=value)
157 return True, index, result
159 def _addition_level_expression_parser(index, tokens):
160 failure = (False, index, None)
162 success, index, result = _multiplication_level_expression_parser(index, tokens)
167 while success and index < len(tokens) and tokens[index].type == 'addition_level_operator':
170 if index + 1 < len(tokens):
171 success, try_index, value = _multiplication_level_expression_parser(index + 1, tokens)
175 '+': FurAdditionExpression,
176 '-': FurSubtractionExpression,
177 }[tokens[index].match](left=result, right=value)
180 return True, index, result
182 def _comma_separated_list_parser(index, tokens):
183 failure = (False, index, None)
187 success, index, expression = _addition_level_expression_parser(index, tokens)
190 expressions.append(expression)
194 while success and index < len(tokens) and tokens[index].type == 'comma':
197 if index + 1 < len(tokens):
198 success, try_index, expression = _addition_level_expression_parser(index + 1, tokens)
201 expressions.append(expression)
204 return True, index, tuple(expressions)
207 FurFunctionCallExpression = collections.namedtuple(
208 'FurFunctionCallExpression',
215 FurProgram = collections.namedtuple(
222 def _function_call_expression_parser(index, tokens):
223 failure = (False, index, None)
225 if tokens[index].type != 'symbol':
227 name = tokens[index].match
230 if tokens[index].type != 'open_parenthese':
234 success, index, arguments = _comma_separated_list_parser(index, tokens)
239 if tokens[index].type != 'close_parenthese':
240 raise Exception('Expected ")", found "{}" on line {}'.format(
246 return True, index, FurFunctionCallExpression(name=name, arguments=arguments)
248 def _program_formatter(statement_list):
249 return FurProgram(statement_list=statement_list)
251 _program_parser = _zero_or_more_parser(_program_formatter, _function_call_expression_parser)
253 def _parse(parser, tokens):
254 success, index, result = parser(0, tokens)
256 if index < len(tokens):
257 raise Exception('Unable to parse token {}'.format(tokens[index]))
262 raise Exception('Unable to parse')
265 return _parse(_program_parser, tokens)
267 if __name__ == '__main__':
272 class FurStringLiteralExpressionParserTests(unittest.TestCase):
273 def test_parses_single_quoted_string_literal(self):
275 _string_literal_expression_parser(0, tokenization.tokenize("'Hello, world'")),
279 FurStringLiteralExpression(value='Hello, world'),
283 class FurFunctionCallExpressionParserTests(unittest.TestCase):
284 def test_parses_function_with_string_literal_argument(self):
286 _function_call_expression_parser(0, tokenization.tokenize("print('Hello, world')")),
290 FurFunctionCallExpression(
292 arguments=(FurStringLiteralExpression(value='Hello, world'),),