Skip to content
← Back

src/syntax/parsers/variables/variable.ghul

1
namespace Syntax.Parsers.Variables is
2
class VARIABLE(
3
identifier_parser: Parser[Trees.Identifiers.Identifier],
4
destructure_left_parser: Parser[Trees.Variables.DESTRUCTURING_VARIABLE_LEFT],
5
type_parser: Parser[Trees.TypeExpressions.TypeExpression],
6
expression_parser: Parser[Trees.Expressions.Expression],
7
modifier_list_parser: Parser[Trees.Modifiers.LIST],
8
pragma_parser: Parser[Trees.Pragmas.PRAGMA]
9
): Base[Trees.Variables.VARIABLE] is
10
super();
11
12
parse(context: CONTEXT) -> Trees.Variables.VARIABLE? is
13
let start = context.location;
14
15
// An attribute pragma before a formal-argument parameter, e.g.
16
// `@FromQuery() id: int`. Only recognised inside a function or
17
// method parameter list (CONTEXT.in_formal_arguments) — a `let`,
18
// primary-ctor header, or variant field list leaves `@` alone
19
// for the caller's usual "unexpected token" handling.
20
let pragmas: Collections.LIST[Trees.Pragmas.PRAGMA]? mut = _;
21
22
if context.in_formal_arguments then
23
while context.current.token == Lexical.TOKEN.AT do
24
let pragma = pragma_parser.parse(context);
25
26
if !pragma? then
27
break;
28
fi
29
30
if !pragmas? then
31
pragmas = Collections.LIST[Trees.Pragmas.PRAGMA]();
32
fi
33
34
pragmas.add(pragma);
35
od
36
fi
37
38
// The .. splice marker in a secondary-init formal-arg list
39
// parses as a synthetic VARIABLE flagged is_splice. The
40
// rewrite-primary-constructors pass expands it into the
41
// surrounding class's primary parameters; no downstream
42
// phase ever observes it. Outside an init parameter list
43
// (the function parser opens / closes the window via
44
// `context.in_init_arguments`) it's a syntax error.
45
if
46
context.current.token == Lexical.TOKEN.OPERATOR /\
47
context.current.value_string =~ ".."
48
then
49
let splice_location = context.location;
50
context.next_token();
51
52
let splice = Trees.Variables.VARIABLE(
53
splice_location,
54
Trees.Identifiers.Identifier(splice_location, "$splice"),
55
Trees.TypeExpressions.INFER(splice_location),
56
false,
57
false,
58
null
59
);
60
61
splice.mark_splice();
62
63
if !context.in_init_arguments then
64
context.error(
65
splice_location,
66
".. is only allowed in an init parameter list"
67
);
68
splice.poison(true);
69
fi
70
71
if pragmas? then
72
context.error(
73
splice_location,
74
"attribute is not allowed on the .. splice marker"
75
);
76
splice.poison(true);
77
fi
78
79
return splice;
80
fi
81
82
let variable_left: Trees.Variables.VariableLeft mut;
83
84
if context.current_token == Lexical.TOKEN.PAREN_OPEN then
85
variable_left = destructure_left_parser.parse(context)!;
86
elif context.current_token == Lexical.TOKEN.IDENTIFIER then
87
let identifier = identifier_parser.parse(context);
88
89
if identifier? then
90
variable_left = Trees.Variables.SIMPLE_VARIABLE_LEFT(identifier.location, identifier);
91
else
92
return null;
93
fi
94
else
95
context.expect_token([Lexical.TOKEN.IDENTIFIER, Lexical.TOKEN.PAREN_OPEN], "in variable");
96
return null;
97
fi
98
99
let end mut = variable_left.location;
100
let type_expression: Trees.TypeExpressions.TypeExpression mut = Trees.TypeExpressions.INFER(start::context.location);
101
let initializer: Trees.Expressions.Expression? mut = _;
102
let is_explicit_type mut = false;
103
104
if context.current.token == Lexical.TOKEN.COLON then
105
is_explicit_type = true;
106
context.next_token();
107
type_expression = type_parser.parse(context)!;
108
109
end = type_expression.location;
110
fi
111
112
let is_mutable_marked mut = false;
113
if context.current_token == Lexical.TOKEN.MUT then
114
context.next_token();
115
is_mutable_marked = true;
116
end = context.location;
117
fi
118
119
// Trailing modifier list — only consumed in primary-ctor
120
// header position. Elsewhere (`let`, formal args, secondary
121
// inits) a stray modifier token falls through to the caller
122
// for normal "unexpected token" handling.
123
let modifiers: Trees.Modifiers.LIST? mut = _;
124
if context.in_primary_ctor_params then
125
modifiers = modifier_list_parser.parse(context)!;
126
if !modifiers.is_empty then
127
end = modifiers.location;
128
fi
129
fi
130
131
if context.current.token == Lexical.TOKEN.ASSIGN then
132
context.next_token();
133
initializer = expression_parser.parse(context)!;
134
end = initializer.location;
135
fi
136
137
let result =
138
Trees.Variables.VARIABLE(
139
start::end,
140
variable_left,
141
type_expression,
142
false,
143
is_explicit_type,
144
initializer
145
);
146
147
if is_mutable_marked then
148
result.mark_mutable();
149
fi
150
151
if modifiers? /\ !modifiers.is_empty then
152
result.set_modifiers(modifiers);
153
fi
154
155
if pragmas? then
156
result.set_pragmas(pragmas);
157
fi
158
159
result.poison(type_expression.is_poisoned);
160
161
return result;
162
si
163
si
164
si