Skip to content
← Back

src/syntax/parsers/definitions/indexer.ghul

1
namespace Syntax.Parsers.Definitions is
2
use IO.Std;
3
4
use Source;
5
6
class INDEXER(
7
identifier_parser: Parser[Trees.Identifiers.Identifier],
8
type_parser: Parser[Trees.TypeExpressions.TypeExpression],
9
modifier_list_parser: Parser[Trees.Modifiers.LIST],
10
variable_parser: Parser[Trees.Variables.VARIABLE],
11
body_parser: Parser[Trees.Bodies.Body]
12
): Base[Trees.Definitions.INDEXER] is
13
description: string => "indexer";
14
15
super();
16
17
parse(context: CONTEXT) -> Trees.Definitions.INDEXER? is
18
let name: Trees.Identifiers.Identifier? mut = null;
19
let start = context.location;
20
21
if context.current.token == Lexical.TOKEN.IDENTIFIER then
22
name = identifier_parser.parse(context);
23
fi
24
25
if !context.next_token(Lexical.TOKEN.SQUARE_OPEN) then
26
return null;
27
fi
28
29
let index_argument = variable_parser.parse(context);
30
31
let fail mut = !context.next_token(Lexical.TOKEN.SQUARE_CLOSE);
32
33
let type_expression: Trees.TypeExpressions.TypeExpression mut;
34
35
if !fail \/ context.current.token == Lexical.TOKEN.COLON then
36
context.next_token();
37
type_expression = type_parser.parse(context)!;
38
39
else
40
type_expression = Trees.TypeExpressions.INFER(context.location);
41
fi
42
43
let modifiers = modifier_list_parser.parse(context)!;
44
let read_body: Trees.Bodies.Body? mut = null;
45
let assign_body: Trees.Bodies.Body? mut = null;
46
let setter_argument_name: Trees.Identifiers.Identifier? mut = null;
47
let expect_semicolon mut = true;
48
49
let progress mut = false;
50
51
do
52
if fail then break ; fi
53
54
if context.current.token == Lexical.TOKEN.ASSIGN then
55
if setter_argument_name? then
56
context.error(context.location, "replacing assign");
57
fi
58
context.next_token();
59
progress = true;
60
setter_argument_name = identifier_parser.parse(context);
61
expect_semicolon = context.current.token != Lexical.TOKEN.COMMA /\ context.current.token != Lexical.TOKEN.IS;
62
assign_body = body_parser.parse(context);
63
if context.current.token == Lexical.TOKEN.COMMA then
64
context.next_token();
65
else
66
break;
67
fi
68
elif context.current.token == Lexical.TOKEN.IS \/ context.current.token == Lexical.TOKEN.ARROW_FAT then
69
expect_semicolon = context.current.token == Lexical.TOKEN.ARROW_FAT;
70
if read_body? then
71
context.error(context.location, "replacing read");
72
fi
73
read_body = body_parser.parse(context);
74
if context.current.token == Lexical.TOKEN.COMMA then
75
progress = true;
76
context.next_token();
77
else
78
break;
79
fi
80
elif context.current_token == Lexical.TOKEN.SEMICOLON then
81
break;
82
elif context.current_token == Lexical.TOKEN.COMMA then
83
if read_body? then
84
context.error(context.location, "replacing read");
85
elif assign_body? then
86
context.error(context.location, "empty read body must precede write body");
87
else
88
progress = true;
89
context.next_token();
90
91
read_body = Syntax.Trees.Bodies.NULL(context.current.location);
92
fi
93
else
94
if !fail then
95
context.error(context.location, "unexpected input in indexer");
96
fi
97
98
fail = true;
99
100
break;
101
fi
102
103
if !progress then
104
Std.error.write_line("no progress in indexer: {context.current_token_name}");
105
return null;
106
fi
107
108
expect_semicolon = true;
109
od
110
111
if context.in_trait /\ read_body == null then
112
read_body = Trees.Bodies.NULL(context.location);
113
fi
114
115
let result: Trees.Definitions.INDEXER? mut = null;
116
117
if index_argument? then
118
result =
119
Trees.Definitions.INDEXER(
120
start::context.location,
121
name,
122
index_argument,
123
type_expression,
124
modifiers,
125
read_body,
126
setter_argument_name,
127
assign_body
128
);
129
fi
130
131
if expect_semicolon then
132
context.next_token(Lexical.TOKEN.SEMICOLON);
133
fi
134
135
return result;
136
si
137
si
138
si