Skip to content
← Back

src/syntax/parsers/definitions/variant.ghul

1
namespace Syntax.Parsers.Definitions is
2
use Source;
3
use Logging;
4
5
class VARIANT(
6
identifier_parser: Parser[Trees.Identifiers.Identifier],
7
variable_list_parser: Parser[Trees.Variables.LIST],
8
modifier_parser: Parser[Trees.Modifiers.LIST]
9
): Base[Trees.Definitions.VARIANT] is
10
super();
11
12
parse(context: CONTEXT) -> Trees.Definitions.VARIANT? is
13
let start = context.location;
14
context.in_classy = true;
15
context.global_indent = start.start_column;
16
17
/*
18
parse a typed-union variant, which is of the form
19
20
variant_definition ::= identifier variant_fields? "default"? ";"
21
variant_fields ::= "(" variant_field ("," variant_field)* ")"
22
variant_field ::= identifier ":" type_expression
23
24
A trailing `default` nominates this variant as the union's
25
default variant — the one `?` and `!` test and unwrap.
26
*/
27
28
try
29
let identifier = identifier_parser.parse(context);
30
31
let should_poison mut = false;
32
33
if !identifier? then
34
return null;
35
fi
36
37
should_poison = identifier.is_poisoned;
38
39
let members: Trees.Variables.LIST mut = Trees.Variables.LIST(start::context.location, System.Array.empty`[Trees.Variables.VARIABLE]());
40
41
if context.current_token == Lexical.TOKEN.PAREN_OPEN then
42
context.next_token();
43
44
let previous_in_init_arguments = context.in_init_arguments;
45
context.in_init_arguments = true;
46
try
47
members = variable_list_parser.parse(context)!;
48
finally
49
context.in_init_arguments = previous_in_init_arguments;
50
yrt
51
52
should_poison = should_poison \/ members.is_poisoned;
53
54
if !should_poison \/ context.current_token == Lexical.TOKEN.PAREN_CLOSE then
55
context.next_token(Lexical.TOKEN.PAREN_CLOSE);
56
fi
57
else
58
59
for m in members do
60
if !m.is_explicit_type then
61
context.error(m.location, "variant field must have an explicit type");
62
should_poison = true;
63
fi
64
od
65
fi
66
67
let modifiers = Trees.Modifiers.LIST(
68
context.location,
69
Trees.Modifiers.PUBLIC(context.location),
70
Trees.Modifiers.FIELD(context.location)
71
);
72
73
let is_default mut = false;
74
75
if context.current_token == Lexical.TOKEN.DEFAULT then
76
is_default = true;
77
context.next_token();
78
fi
79
80
let semicolon_end = context.location;
81
82
if !should_poison \/ context.current_token == Lexical.TOKEN.SEMICOLON then
83
context.next_token(Lexical.TOKEN.SEMICOLON);
84
fi
85
86
let result = Trees.Definitions.VARIANT(
87
start::semicolon_end,
88
identifier!,
89
members,
90
modifiers
91
);
92
93
result.is_default = is_default;
94
result.poison(should_poison);
95
96
return result;
97
finally
98
context.in_classy = false;
99
yrt
100
si
101
si
102
si