Allocate Fur stacks on the C heap
[fur] / parsing.py
index 45964d7..12b93f5 100644 (file)
@@ -36,6 +36,14 @@ def _zero_or_more_parser(formatter, parser):
 
     return result_parser
 
+NodeMetadata = collections.namedtuple(
+    'NodeMetadata',
+    [
+        'index',
+        'line',
+    ],
+)
+
 FurIntegerLiteralExpression = collections.namedtuple(
     'FurIntegerLiteralExpression',
     [
@@ -67,6 +75,7 @@ FurNegationExpression = collections.namedtuple(
 FurInfixExpression = collections.namedtuple(
     'FurInfixExpression',
     [
+        'metadata',
         'order',
         'operator',
         'left',
@@ -90,6 +99,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)
 
@@ -101,6 +125,9 @@ def _integer_literal_expression_parser(index, tokens):
     return True, index, FurIntegerLiteralExpression(integer=value)
 
 def _string_literal_expression_parser(index, tokens):
+    if tokens[index].type == 'double_quoted_string_literal':
+        return (True, index + 1, FurStringLiteralExpression(string=tokens[index].match[1:-1]))
+
     if tokens[index].type == 'single_quoted_string_literal':
         return (True, index + 1, FurStringLiteralExpression(string=tokens[index].match[1:-1]))
 
@@ -147,6 +174,44 @@ 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 _list_literal_expression_parser(index, tokens):
     failure = (False, index, None)
 
@@ -159,29 +224,42 @@ 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,
+        _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)
+    success, index, value = _dot_expression_parser(index + 1, tokens)
 
     if not success:
         return failure
 
     return (True, index, FurNegationExpression(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):
@@ -201,6 +279,10 @@ def _left_recursive_infix_operator_parser(operator_token_matcher, operand_parser
 
             if success:
                 result = FurInfixExpression(
+                    metadata=NodeMetadata(
+                        index=tokens[index].index,
+                        line=tokens[index].line,
+                    ),
                     order=order,
                     operator=tokens[index].match,
                     left=result,
@@ -215,7 +297,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)
 
@@ -445,9 +527,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