Skip to content
← Back

src/syntax/parsers/definitions/property.ghul

1
namespace Syntax.Parsers.Definitions is
2
use IO.Std;
3
4
use Source;
5
6
use Logging;
7
8
class PROPERTY(
9
identifier_parser: Parser[Trees.Identifiers.Identifier],
10
type_parser: Parser[Trees.TypeExpressions.TypeExpression],
11
modifier_list_parser: Parser[Trees.Modifiers.LIST],
12
body_parser: Parser[Trees.Bodies.Body]
13
): Base[Trees.Definitions.PROPERTY] is
14
super();
15
16
parse(context: CONTEXT) -> Trees.Definitions.PROPERTY is
17
let fail mut = false;
18
let progress mut = false;
19
20
try
21
if context.in_classy then
22
context.in_member = true;
23
context.member_indent = context.location.start_column
24
else
25
context.in_global_function = true;
26
context.global_indent = context.location.start_column;
27
fi
28
29
let start = context.location;
30
let name = identifier_parser.parse(context);
31
let type_expression: Trees.TypeExpressions.TypeExpression mut;
32
33
if context.current.token == Lexical.TOKEN.COLON then
34
context.next_token();
35
progress = true;
36
37
type_expression = type_parser.parse(context)!;
38
39
if type_expression == null \/ type_expression.is_poisoned then
40
fail = true;
41
fi
42
else
43
type_expression = Trees.TypeExpressions.INFER(context.location);
44
fi
45
46
let modifiers = modifier_list_parser.parse(context)!;
47
let read_body: Trees.Bodies.Body? mut = null;
48
let assign_body: Trees.Bodies.Body? mut = null;
49
let setter_argument_name: Trees.Identifiers.Identifier? mut = null;
50
let expect_semicolon mut = true;
51
52
do
53
if context.current.token == Lexical.TOKEN.ASSIGN then
54
if setter_argument_name? then
55
context.error(context.location, "replacing assign");
56
fi
57
58
context.next_token();
59
progress = true;
60
61
setter_argument_name = identifier_parser.parse(context);
62
expect_semicolon = context.current.token == Lexical.TOKEN.ARROW_FAT \/ context.current.token == Lexical.TOKEN.INNATE;
63
64
try
65
assign_body = body_parser.parse(context);
66
catch ue: UNWIND_TO_MEMBER_EXCEPTION
67
assign_body = Trees.Bodies.NULL(context.location);
68
fail = true;
69
yrt
70
71
if context.current.token == Lexical.TOKEN.COMMA then
72
context.next_token();
73
progress = true;
74
else
75
if isa Trees.Bodies.NULL(assign_body) then
76
expect_semicolon = true;
77
fi
78
79
break;
80
fi
81
elif
82
context.current.token == Lexical.TOKEN.IS \/
83
context.current.token == Lexical.TOKEN.ARROW_FAT \/
84
context.current.token == Lexical.TOKEN.INNATE
85
then
86
expect_semicolon = context.current.token == Lexical.TOKEN.ARROW_FAT \/ context.current.token == Lexical.TOKEN.INNATE;
87
88
if read_body? then
89
context.error(context.location, "replacing read");
90
fi
91
92
try
93
read_body = body_parser.parse(context);
94
catch ue: UNWIND_TO_MEMBER_EXCEPTION
95
read_body = Trees.Bodies.NULL(context.location);
96
fail = true;
97
yrt
98
99
if context.current.token == Lexical.TOKEN.COMMA then
100
context.next_token();
101
progress = true;
102
else
103
if isa Trees.Bodies.NULL(read_body) then
104
expect_semicolon = true;
105
else
106
progress = true;
107
fi
108
109
break;
110
fi
111
elif context.current_token == Lexical.TOKEN.SEMICOLON then
112
break;
113
elif context.current_token == Lexical.TOKEN.COMMA then
114
if read_body? then
115
context.error(context.location, "replacing read");
116
elif assign_body? then
117
context.error(context.location, "empty read body must precede write body");
118
else
119
progress = true;
120
context.next_token();
121
122
read_body = Syntax.Trees.Bodies.NULL(context.current.location);
123
fi
124
else
125
if !fail then
126
context.error(context.location, "syntax error in property: unexpected token {context.current_token_name}");
127
fi
128
129
fail = true;
130
131
break;
132
fi
133
134
expect_semicolon = true;
135
od
136
137
if context.in_trait /\ read_body == null then
138
read_body = Trees.Bodies.NULL(context.location);
139
fi
140
141
let result =
142
Trees.Definitions.PROPERTY(
143
start::context.location,
144
type_expression,
145
name,
146
modifiers,
147
read_body,
148
setter_argument_name,
149
assign_body
150
);
151
152
if expect_semicolon then
153
if !fail \/ context.current.token == Lexical.TOKEN.SEMICOLON then
154
context.next_token(Lexical.TOKEN.SEMICOLON);
155
fi
156
fi
157
158
if fail /\ !progress then
159
debug_always("no progress parsing property at {context.location}");
160
IoC.CONTAINER.instance.watchdog.request_restart();
161
162
context.error(context.location, "syntax error in property: unexpected token {context.current_token_name}");
163
context.next_token();
164
165
throw UNWIND_BAD_PROPERTY_EXCEPTION(null);
166
fi
167
168
result.poison(fail);
169
170
return result;
171
finally
172
context.in_member = false;
173
yrt
174
si
175
si
176
si