Skip to content
← Back

src/syntax/parsers/variables/list.ghul

1
namespace Syntax.Parsers.Variables is
2
use Source;
3
use Logging;
4
5
class LIST(variable_parser: Parser[Trees.Variables.VARIABLE]): Base[Trees.Variables.LIST] is
6
allow_empty: bool;
7
8
super();
9
10
parse(context: CONTEXT) -> Trees.Variables.LIST is
11
let start = context.location;
12
let end mut = context.location;
13
let variables = Collections.LIST[Trees.Variables.VARIABLE]();
14
15
if
16
context.current_token == Lexical.TOKEN.IDENTIFIER \/
17
context.current_token == Lexical.TOKEN.PAREN_OPEN \/
18
(context.current.token == Lexical.TOKEN.OPERATOR /\ context.current.value_string =~ "..") \/
19
(context.in_formal_arguments /\ context.current_token == Lexical.TOKEN.AT) \/
20
!allow_empty
21
then
22
do
23
let variable: Trees.Variables.VARIABLE? mut;
24
25
variable = variable_parser.parse(context);
26
27
if variable? /\ variable.is_variable then
28
// FIXME: parsing destructure list within an argument list probably
29
// makes this more fragile, and we don't support it anyway - should
30
// disable destructure list parsing in in the variable list parser
31
// when parsing an argument list
32
33
if context.current.token == Lexical.TOKEN.PAREN_OPEN then
34
if variable.is_explicit_type then
35
// we've probably just absorbed the name of a following
36
// function declaration
37
38
// exclude the type from the variable's location
39
// to stop the error message running on into
40
// the following function declaration
41
let name_location = variable.name!.location;
42
43
end = name_location;
44
45
// clear the type expression so we don't report a spurious error
46
// about it being undefined
47
variable.set_type_expression(Trees.TypeExpressions.INFER(name_location));
48
49
variables.add(variable);
50
else
51
context.expect_token(Lexical.TOKEN.COLON);
52
fi
53
54
break;
55
fi
56
57
end = variable.location;
58
59
variables.add(variable);
60
61
if
62
context.current.token == Lexical.TOKEN.IDENTIFIER /\
63
context.location.start_line >= variable.location.start_line /\
64
context.location.start_column > variable.location.end_column
65
then
66
context.expect_token(Lexical.TOKEN.COMMA);
67
elif context.is_end_of_file \/ context.current.token != Lexical.TOKEN.COMMA then
68
break;
69
else
70
end = context.location;
71
context.next_token();
72
73
// Trailing comma: stop when what follows
74
// can't start another variable. Permits
75
// formal-argument lists, let-statement
76
// variable lists, and destructuring
77
// patterns to end with a comma.
78
if
79
context.current.token != Lexical.TOKEN.IDENTIFIER /\
80
context.current.token != Lexical.TOKEN.PAREN_OPEN /\
81
!(context.current.token == Lexical.TOKEN.OPERATOR /\ context.current.value_string =~ "..") /\
82
!(context.in_formal_arguments /\ context.current.token == Lexical.TOKEN.AT)
83
then
84
break;
85
fi
86
fi
87
88
else
89
break;
90
fi
91
od
92
fi
93
94
return Trees.Variables.LIST(start::end, variables);
95
si
96
si
97
si