Skip to content
← Back

src/syntax/parsers/definitions/definition_resync.ghul

1
namespace Syntax.Parsers.Definitions is
2
use Source
3
4
// Where a definition list picks up again after a definition it could
5
// not parse. The tokens between the mistake and the next definition
6
// belong to the definition that went wrong, so reading each of them as
7
// a definition of its own reports the one mistake once per token and
8
// takes whatever it can make of the rest - a damaged header's body read
9
// as members, say.
10
//
11
// So the list skips them, reporting nothing, and resumes at:
12
//
13
// a token some construct still being parsed would end at, read from
14
// those parsers as the statement layer reads it (see
15
// CONTEXT._awaited_enders) - the `si` of the enclosing type or
16
// namespace, which the list itself must see;
17
// a keyword that can only begin a definition, wherever it stands;
18
// the start of a line, since the rest of the line the mistake is on
19
// belongs to the definition that went wrong, and a later line is
20
// read as whatever it is.
21
//
22
// Nothing is counted: the source being recovered from is
23
// incomplete, so a count taken from its brackets is a count of the
24
// mistake.
25
class DEFINITION_RESYNC is
26
init() is si
27
28
// After a definition attempt that started at `attempt_start` with
29
// `errors_before` errors logged.
30
recover(context: CONTEXT, attempt_start: LOCATION, errors_before: int) is
31
if context.logger.error_count == errors_before then
32
return
33
fi
34
35
// An attempt that consumed nothing has to be moved past, or the
36
// list would try the same parse at the same place again.
37
let consumed mut = context.location.start != attempt_start.start
38
39
while !context.is_end_of_file do
40
if context.is_awaited_ender(context.current_token) then
41
break
42
fi
43
44
if consumed /\ _at_resync_point(context) then
45
break
46
fi
47
48
context.next_token()
49
50
consumed = true
51
od
52
si
53
54
_at_resync_point(context: CONTEXT) -> bool =>
55
_starts_only_a_definition(context.current_token) \/ context.current.first_on_line
56
57
_starts_only_a_definition(token: Lexical.TOKEN) -> bool =>
58
token == Lexical.TOKEN.NAMESPACE \/
59
token == Lexical.TOKEN.USE \/
60
token == Lexical.TOKEN.CLASS \/
61
token == Lexical.TOKEN.TRAIT \/
62
token == Lexical.TOKEN.STRUCT \/
63
token == Lexical.TOKEN.PARTIAL \/
64
token == Lexical.TOKEN.IMPL \/
65
token == Lexical.TOKEN.UNION \/
66
token == Lexical.TOKEN.ENUM \/
67
token == Lexical.TOKEN.AT
68
si
69
si