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 _integer_literal_expression_parser,
110 _string_literal_expression_parser,
113 def _multiplication_level_expression_parser(index, tokens):
114 failure = (False, index, None)
116 success, index, result = _literal_level_expression_parser(index, tokens)
121 while success and index < len(tokens) and tokens[index].type == 'multiplication_level_operator':
124 if index + 1 < len(tokens):
125 success, try_index, value = _literal_level_expression_parser(index + 1, tokens)
129 '*': FurMultiplicationExpression,
130 '//': FurIntegerDivisionExpression,
131 '%': FurModularDivisionExpression,
132 }[tokens[index].match](left=result, right=value)
135 return True, index, result
137 def _addition_level_expression_parser(index, tokens):
138 failure = (False, index, None)
140 success, index, result = _multiplication_level_expression_parser(index, tokens)
145 while success and index < len(tokens) and tokens[index].type == 'addition_level_operator':
148 if index + 1 < len(tokens):
149 success, try_index, value = _multiplication_level_expression_parser(index + 1, tokens)
153 '+': FurAdditionExpression,
154 '-': FurSubtractionExpression,
155 }[tokens[index].match](left=result, right=value)
158 return True, index, result
160 FunctionCall = collections.namedtuple(
168 FurProgram = collections.namedtuple(
175 def _function_call_parser(index, tokens):
176 failure = (False, index, None)
178 if tokens[index].type != 'symbol':
180 name = tokens[index].match
183 if tokens[index].type != 'open_parenthese':
187 success, index, argument = _addition_level_expression_parser(index, tokens)
192 if tokens[index].type != 'close_parenthese':
196 return True, index, FunctionCall(name=name, arguments=(argument,))
198 def _program_formatter(statement_list):
199 return FurProgram(statement_list=statement_list)
201 _program_parser = _zero_or_more_parser(_program_formatter, _function_call_parser)
203 def _parse(parser, tokens):
204 success, index, result = parser(0, tokens)
206 if index < len(tokens):
207 raise Exception('Unable to parse token {}'.format(tokens[index]))
212 raise Exception('Unable to parse')
216 return _parse(_program_parser, tokens)
218 if __name__ == '__main__':
223 class FurStringLiteralExpressionParserTests(unittest.TestCase):
224 def test_parses_single_quoted_string_literal(self):
226 _string_literal_expression_parser(0, tokenization.tokenize("'Hello, world'")),
230 FurStringLiteralExpression(value='Hello, world'),
234 class FunctionCallParserTests(unittest.TestCase):
235 def test_parses_function_with_string_literal_argument(self):
237 _function_call_parser(0, tokenization.tokenize("print('Hello, world')")),
243 arguments=(FurStringLiteralExpression(value='Hello, world'),),