Skip to content
← Back

src/syntax/parsers/base.ghul

1
namespace Syntax.Parsers is
2
use System.Exception
3
4
trait Parser[T: class] is
5
// Null means the parser could not produce a result — parsers
6
// return null on unparseable input as part of error recovery,
7
// so every caller sees the possibility in the type.
8
parse(context: CONTEXT) -> T?
9
si
10
11
class Base[T: class]: Parser[T] abstract is
12
_expected_tokens: Collections.MutableList[Lexical.TOKEN]?
13
parsers: Collections.MAP[Lexical.TOKEN, (CONTEXT) -> T?]
14
15
expected_tokens: Collections.Iterable[Lexical.TOKEN] is
16
let result = _expected_tokens ?? _build_expected_tokens()
17
18
_expected_tokens = result
19
20
return result
21
si
22
23
description: string? => null
24
25
syntax_error_message: string =>
26
let d = description in
27
if d? then
28
"in {d}"
29
else
30
"syntax error"
31
fi
32
33
init() is
34
parsers = Collections.MAP[Lexical.TOKEN, (CONTEXT) -> T?]()
35
si
36
37
add_parser(p: (CONTEXT) -> T?, token: Lexical.TOKEN) is
38
if parsers.contains_key(token) then
39
throw Exception("{token} already has a parser ({p})")
40
fi
41
42
parsers[token] = p
43
si
44
45
add_parser(p: (CONTEXT) -> T?, tokens: Collections.Iterable[Lexical.TOKEN]) is
46
for t in tokens do
47
add_parser(p, t)
48
od
49
si
50
51
parse(context: CONTEXT) -> T? is
52
let token = context.current.token
53
54
return
55
if parsers.contains_key(token) then
56
let p = parsers[token]
57
58
p(context)
59
else
60
other_token(context)
61
fi
62
si
63
64
other_token(context: CONTEXT) -> T? is
65
if context.current.token != Lexical.TOKEN.CANCEL_STRING then
66
context.error(context.location,
67
"{syntax_error_message}: expected {Lexical.TOKEN_NAMES[expected_tokens]} but found {context.current_token_name}"
68
)
69
fi
70
return _
71
si
72
73
_build_expected_tokens() -> Collections.MutableList[Lexical.TOKEN] is
74
let et = Collections.LIST[Lexical.TOKEN]()
75
76
for k in parsers.keys do
77
et.add(k)
78
od
79
80
assert et.count > 0 else "should have at least one expected token"
81
82
return et
83
si
84
si
85
si