Skip to content
← Back

src/syntax/parsers/statements/list.ghul

1
namespace Syntax.Parsers.Statements is
2
use System.Exception;
3
4
use IO.Std;
5
6
use Source;
7
8
use Ghul.Pipes;
9
10
class LIST(
11
terminators: Collections.LIST[Lexical.TOKEN],
12
statement_parser: Parser[Trees.Statements.Statement]
13
): Base[Trees.Statements.LIST] is
14
terminators: Collections.List[Lexical.TOKEN];
15
description: string => "statement list";
16
17
super();
18
19
parse(context: CONTEXT) -> Trees.Statements.LIST is
20
self.terminators = terminators;
21
22
let start = context.location;
23
let end mut = context.location;
24
let statements = Collections.LIST[Trees.Statements.Statement]();
25
26
let want_semicolon mut = false;
27
28
while !context.is_end_of_file /\ !at_terminator(context) do
29
if context.current.token == Lexical.TOKEN.SEMICOLON then
30
context.next_token();
31
32
// TODO potentially unnecessary semi-colon, but reporting
33
// them all is too noisy, at least for the compiler itself
34
// which has thousands of them.
35
36
want_semicolon = false;
37
elif want_semicolon then
38
context.next_token(Lexical.TOKEN.SEMICOLON);
39
want_semicolon = false;
40
else
41
try
42
let statement = statement_parser.parse(context);
43
44
if statement? then
45
statements.add(statement);
46
want_semicolon = statement.expects_semicolon;
47
48
end = statement.location;
49
else
50
// the statement parser reported its errors and gave up:
51
// skip ahead so the unparsed tokens don't produce a
52
// cascade of follow-on errors
53
end = recover_to_terminator(context);
54
fi
55
catch e: UnwindException
56
throw e;
57
catch e: Exception
58
end = recover_to_terminator(context);
59
yrt
60
fi
61
od
62
63
return Trees.Statements.LIST(start::end, statements);
64
si
65
66
at_terminator(context: CONTEXT) -> bool => terminators |> any(t => t == context.current_token);
67
68
recover_to_terminator(context: CONTEXT) -> LOCATION is
69
let end mut = context.current.location;
70
71
while !at_terminator(context) do
72
end = context.current.location;
73
74
context.next_token();
75
od
76
77
return end;
78
si
79
si
80
si