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 FurAdditionExpression = collections.namedtuple(
48 'FurAdditionExpression',
55 FurSubtractionExpression = collections.namedtuple(
56 'FurSubtractionExpression',
63 FurMultiplicationExpression = collections.namedtuple(
64 'FurMultiplicationExpression',
71 FurIntegerDivisionExpression = collections.namedtuple(
72 'FurIntegerDivisionExpression',
79 FurModularDivisionExpression = collections.namedtuple(
80 'FurModularDivisionExpression',
87 def _integer_literal_expression_parser(index, tokens):
88 failure = (False, index, None)
90 if tokens[index].type != 'integer_literal':
92 value = int(tokens[index].match)
95 return True, index, FurIntegerLiteralExpression(value=value)
97 def _string_literal_expression_parser(index, tokens):
98 failure = (False, index, None)
100 if tokens[index].type != 'single_quoted_string_literal':
102 value = tokens[index].match[1:-1]
105 return True, index, FurStringLiteralExpression(value=value)
107 def _literal_level_expression_parser(index, tokens):
109 _function_call_expression_parser,
110 _integer_literal_expression_parser,
111 _string_literal_expression_parser,
114 def _multiplication_level_expression_parser(index, tokens):
115 failure = (False, index, None)
117 success, index, result = _literal_level_expression_parser(index, tokens)
122 while success and index < len(tokens) and tokens[index].type == 'multiplication_level_operator':
125 if index + 1 < len(tokens):
126 success, try_index, value = _literal_level_expression_parser(index + 1, tokens)
130 '*': FurMultiplicationExpression,
131 '//': FurIntegerDivisionExpression,
132 '%': FurModularDivisionExpression,
133 }[tokens[index].match](left=result, right=value)
136 return True, index, result
138 def _addition_level_expression_parser(index, tokens):
139 failure = (False, index, None)
141 success, index, result = _multiplication_level_expression_parser(index, tokens)
146 while success and index < len(tokens) and tokens[index].type == 'addition_level_operator':
149 if index + 1 < len(tokens):
150 success, try_index, value = _multiplication_level_expression_parser(index + 1, tokens)
154 '+': FurAdditionExpression,
155 '-': FurSubtractionExpression,
156 }[tokens[index].match](left=result, right=value)
159 return True, index, result
161 def _comma_separated_list_parser(index, tokens):
162 failure = (False, index, None)
166 success, index, expression = _addition_level_expression_parser(index, tokens)
169 expressions.append(expression)
173 while success and index < len(tokens) and tokens[index].type == 'comma':
176 if index + 1 < len(tokens):
177 success, try_index, expression = _addition_level_expression_parser(index + 1, tokens)
180 expressions.append(expression)
183 return True, index, tuple(expressions)
186 FurFunctionCallExpression = collections.namedtuple(
187 'FurFunctionCallExpression',
194 FurProgram = collections.namedtuple(
201 def _function_call_expression_parser(index, tokens):
202 failure = (False, index, None)
204 if tokens[index].type != 'symbol':
206 name = tokens[index].match
209 if tokens[index].type != 'open_parenthese':
213 success, index, arguments = _comma_separated_list_parser(index, tokens)
218 if tokens[index].type != 'close_parenthese':
219 raise Exception('Expected ")", found "{}" on line {}'.format(
225 return True, index, FurFunctionCallExpression(name=name, arguments=arguments)
227 def _program_formatter(statement_list):
228 return FurProgram(statement_list=statement_list)
230 _program_parser = _zero_or_more_parser(_program_formatter, _function_call_expression_parser)
232 def _parse(parser, tokens):
233 success, index, result = parser(0, tokens)
235 if index < len(tokens):
236 raise Exception('Unable to parse token {}'.format(tokens[index]))
241 raise Exception('Unable to parse')
244 return _parse(_program_parser, tokens)
246 if __name__ == '__main__':
251 class FurStringLiteralExpressionParserTests(unittest.TestCase):
252 def test_parses_single_quoted_string_literal(self):
254 _string_literal_expression_parser(0, tokenization.tokenize("'Hello, world'")),
258 FurStringLiteralExpression(value='Hello, world'),
262 class FurFunctionCallExpressionParserTests(unittest.TestCase):
263 def test_parses_function_with_string_literal_argument(self):
265 _function_call_expression_parser(0, tokenization.tokenize("print('Hello, world')")),
269 FurFunctionCallExpression(
271 arguments=(FurStringLiteralExpression(value='Hello, world'),),