X-Git-Url: https://code.kerkeslager.com/?p=fur;a=blobdiff_plain;f=parsing.py;h=20ac3761252a577523034493d347383c4b9fcdd4;hp=f16af14deff75305662685b5393fddeb950d4766;hb=HEAD;hpb=02d64def49065ad614fe0ee2a85060666552192e diff --git a/parsing.py b/parsing.py index f16af14..20ac376 100644 --- a/parsing.py +++ b/parsing.py @@ -43,6 +43,14 @@ FurIntegerLiteralExpression = collections.namedtuple( ], ) +FurLambdaExpression = collections.namedtuple( + 'FurLambdaExpression', + ( + 'argument_name_list', + 'statement_list', + ), +) + FurStringLiteralExpression = collections.namedtuple( 'FurStringLiteralExpression', [ @@ -53,6 +61,7 @@ FurStringLiteralExpression = collections.namedtuple( FurSymbolExpression = collections.namedtuple( 'FurSymbolExpression', [ + 'metadata', 'symbol', ], ) @@ -60,6 +69,7 @@ FurSymbolExpression = collections.namedtuple( FurNegationExpression = collections.namedtuple( 'FurNegationExpression', [ + 'metadata', 'value', ], ) @@ -67,6 +77,7 @@ FurNegationExpression = collections.namedtuple( FurInfixExpression = collections.namedtuple( 'FurInfixExpression', [ + 'metadata', 'order', 'operator', 'left', @@ -90,6 +101,21 @@ FurIfExpression = collections.namedtuple( ], ) +FurSymbolExpressionPair = collections.namedtuple( + 'FurSymbolExpressionPair', + [ + 'symbol', + 'expression', + ], +) + +FurStructureLiteralExpression = collections.namedtuple( + 'FurStructureLiteralExpression', + [ + 'fields', + ], +) + def _integer_literal_expression_parser(index, tokens): failure = (False, index, None) @@ -111,7 +137,14 @@ def _string_literal_expression_parser(index, tokens): def _symbol_expression_parser(index, tokens): if tokens[index].type == 'symbol': - return (True, index + 1, FurSymbolExpression(symbol=tokens[index].match)) + return ( + True, + index + 1, + FurSymbolExpression( + metadata=tokens[index].metadata, + symbol=tokens[index].match, + ), + ) return (False, index, None) @@ -150,6 +183,94 @@ def _parenthese_wrapped_parser(internal_parser): def _parenthesized_expression_parser(index, tokens): return _parenthese_wrapped_parser(_expression_parser)(index, tokens) +def symbol_expression_pair_parser(index, tokens): + failure = (False, index, None) + + if tokens[index].type == 'symbol': + symbol = tokens[index].match + index += 1 + else: + return failure + + if tokens[index].type == 'colon': + index += 1 + else: + return failure + + success, index, expression = _expression_parser(index, tokens) + + if not success: + raise Exception() + + return ( + True, + index, + FurSymbolExpressionPair( + symbol=symbol, + expression=expression, + ), + ) + +def _structure_literal_parser(index, tokens): + success, index, result = _parenthese_wrapped_parser(_comma_separated_list_parser(symbol_expression_pair_parser))(index, tokens) + return ( + success, + index, + FurStructureLiteralExpression( + fields=result, + ), + ) + +def _lambda_expression_parser(index, tokens): + failure = (False, index, None) + + if tokens[index].type == 'keyword' and tokens[index].match == 'lambda': + index += 1 + else: + return failure + + if tokens[index].type == 'open_parenthese': + index += 1 + else: + raise Exception('Expected "(", found "{}" on line {}'.format( + tokens[index].match, + tokens[index].metadata.line, + )) + + success, index, argument_name_list = _comma_separated_list_parser(_symbol_expression_parser)( + index, + tokens, + ) + + if tokens[index].type == 'close_parenthese': + index += 1 + else: + raise Exception('Expected ")", found "{}" on line {}'.format( + tokens[index].match, + tokens[index].line, + )) + + if tokens[index].match == 'do': + index += 1 + else: + return failure + + success, index, statement_list = _zero_or_more_parser(tuple, _statement_parser)(index, tokens) + + _, index, _ = consume_newlines(index, tokens) + + if tokens[index].type == 'keyword' and tokens[index].match == 'end': + index += 1 + else: + return failure + + return True, index, FurLambdaExpression( + argument_name_list=tuple(an.symbol for an in argument_name_list), + statement_list=statement_list, + ) + + + def _list_literal_expression_parser(index, tokens): failure = (False, index, None) @@ -162,29 +283,45 @@ def _list_literal_expression_parser(index, tokens): else: return failure +def _literal_level_expression_parser(index, tokens): + return _or_parser( + _list_item_expression_parser, + _function_call_expression_parser, + _parenthesized_expression_parser, + _integer_literal_expression_parser, + _string_literal_expression_parser, + _list_literal_expression_parser, + _lambda_expression_parser, + _symbol_expression_parser, + _structure_literal_parser, + )(index, tokens) + +def _dot_expression_parser(index, tokens): + return _left_recursive_infix_operator_parser( + lambda token: token.type == 'period', + _literal_level_expression_parser, + 'dot_level', + )(index, tokens) + def _negation_expression_parser(index, tokens): failure = (False, index, None) if tokens[index].match != '-': return failure - success, index, value = _literal_level_expression_parser(index + 1, tokens) + metadata = tokens[index].metadata + + success, index, value = _dot_expression_parser(index + 1, tokens) if not success: return failure - return (True, index, FurNegationExpression(value=value)) + return (True, index, FurNegationExpression(metadata=metadata, value=value)) -def _literal_level_expression_parser(index, tokens): +def _negation_level_expression_parser(index, tokens): return _or_parser( + _dot_expression_parser, _negation_expression_parser, - _list_item_expression_parser, - _function_call_expression_parser, - _parenthesized_expression_parser, - _integer_literal_expression_parser, - _string_literal_expression_parser, - _list_literal_expression_parser, - _symbol_expression_parser, )(index, tokens) def _left_recursive_infix_operator_parser(operator_token_matcher, operand_parser, order): @@ -204,6 +341,7 @@ def _left_recursive_infix_operator_parser(operator_token_matcher, operand_parser if success: result = FurInfixExpression( + metadata=tokens[index].metadata, order=order, operator=tokens[index].match, left=result, @@ -218,7 +356,7 @@ def _left_recursive_infix_operator_parser(operator_token_matcher, operand_parser def _multiplication_level_expression_parser(index, tokens): return _left_recursive_infix_operator_parser( lambda token: token.type == 'multiplication_level_operator', - _literal_level_expression_parser, + _negation_level_expression_parser, 'multiplication_level', )(index, tokens) @@ -289,6 +427,7 @@ FurListItemExpression = collections.namedtuple( 'FurListItemExpression', [ 'list_expression', + 'metadata', 'index_expression', ], ) @@ -296,6 +435,7 @@ FurListItemExpression = collections.namedtuple( FurFunctionCallExpression = collections.namedtuple( 'FurFunctionCallExpression', [ + 'metadata', 'function', 'arguments', ], @@ -345,6 +485,8 @@ def _list_item_expression_parser(index, tokens): if not success: return failure + metadata = tokens[index].metadata + success, index, index_expression = _bracket_wrapped_parser(_expression_parser)( index, tokens, @@ -358,9 +500,12 @@ def _list_item_expression_parser(index, tokens): # We can't give this a better name without a bunch of checks, however. list_expression = FurListItemExpression( list_expression=list_expression, + metadata=metadata, index_expression=index_expression, ) + metadata = tokens[index].metadata + success, index, index_expression = _bracket_wrapped_parser(_expression_parser)( index, tokens, @@ -381,6 +526,8 @@ def _function_call_expression_parser(index, tokens): if not success: return failure + metadata = tokens[index].metadata + success, index, arguments = _parenthese_wrapped_parser(_comma_separated_expression_list_parser)( index, tokens, @@ -393,10 +540,13 @@ def _function_call_expression_parser(index, tokens): # "function" is actually the full function call if the next parse attempt doesn't succeed # We can't give this a better name without a bunch of checks, however. function = FurFunctionCallExpression( + metadata=metadata, function=function, arguments=arguments, ) + metadata = tokens[index].metadata + success, index, arguments = _parenthese_wrapped_parser(_comma_separated_expression_list_parser)( index, tokens, @@ -448,9 +598,6 @@ def _if_expression_parser(index, tokens): ), ) - - - _expression_parser = _or_parser( _or_level_expression_parser, _if_expression_parser, # This should always be at the top level @@ -473,7 +620,7 @@ def _assignment_statement_parser(index, tokens): if tokens[index].type == 'symbol': target = tokens[index].match - target_assignment_line = tokens[index].line + target_assignment_line = tokens[index].metadata.line index += 1 else: @@ -554,7 +701,7 @@ def _function_definition_statement_parser(index, tokens): return True, index, FurFunctionDefinitionStatement( name=name, - argument_name_list=tuple(an.symbol for an in argument_name_list), + argument_name_list=tuple(an.symbol for an in argument_name_list), statement_list=statement_list, )