Skip to content
← Back

src/syntax/parsers/expressions/tuple.ghul

1
namespace Syntax.Parsers.Expressions is
2
use IO.Std;
3
4
use Source;
5
6
use Ghul.Pipes;
7
8
class TUPLE(
9
expression_list_parser: Parser[Trees.Expressions.LIST],
10
type_parser: Parser[Trees.TypeExpressions.TypeExpression]
11
): Base[Trees.Expressions.TUPLE] is
12
description: string => "tuple";
13
14
super();
15
16
parse(context: CONTEXT) -> Trees.Expressions.TUPLE is
17
let start = context.location;
18
19
// Parsing the elements runs the enclosing list loop again,
20
// which clears `allow_tuple_element`, so capture here
21
// whether this group is itself in a position that could be
22
// a lambda's formal parameter.
23
let could_be_formal_argument = context.allow_tuple_element;
24
25
context.next_token(Lexical.TOKEN.PAREN_OPEN, syntax_error_message);
26
27
let expressions: Trees.Expressions.LIST mut;
28
29
if context.current.token != Lexical.TOKEN.PAREN_CLOSE then
30
expressions = expression_list_parser.parse(context)!;
31
else
32
expressions = Trees.Expressions.LIST(context.location, Collections.LIST[Trees.Expressions.Expression]());
33
fi
34
35
expressions.rewrite_as_tuple_elements();
36
37
context.next_token(Lexical.TOKEN.PAREN_CLOSE, syntax_error_message);
38
39
let end mut = context.location;
40
41
// `(a, b): T` - a type ascription on a parenthesised group.
42
// Only meaningful where the group could be a lambda's
43
// formal parameter, which is exactly where
44
// `allow_tuple_element` is set, so restrict it to there and
45
// leave the `:` for the caller to report anywhere else. A
46
// group destructures anything positionally, not just a
47
// tuple, so the ascription takes the full type syntax.
48
let type_expression: Trees.TypeExpressions.TypeExpression? mut = null;
49
50
// ... and only when every element could be a pattern
51
// element. `(1, 2): T` cannot be a parameter however it is
52
// used, so leave its `:` to be reported where it always
53
// was rather than consuming it and dropping the type.
54
let could_be_pattern =
55
expressions.expressions.count > 1 /\
56
expressions.expressions |> all(e => e.try_copy_as_variable_left()?);
57
58
if
59
could_be_formal_argument /\
60
could_be_pattern /\
61
context.current.token == Lexical.TOKEN.COLON
62
then
63
context.next_token();
64
65
type_expression = type_parser.parse(context)!;
66
end = type_expression.location;
67
fi
68
69
let result = Trees.Expressions.TUPLE(start::end, expressions, false);
70
71
if type_expression? then
72
result.set_type_expression(type_expression);
73
fi
74
75
return result;
76
si
77
si
78
si