Skip to content
← Back

src/syntax/parsers/definitions/precedence.ghul

1
namespace Syntax.Parsers.Definitions is
2
use Collections.MAP
3
use Collections.MutableMap
4
5
use Syntax.Parsers.Expressions.PRECEDENCE
6
7
use Source
8
9
// Shared by a per-definition `@precedence` and a file-level
10
// `@@precedence`: validates the pragma's operator and precedence
11
// arguments and installs the operator's precedence into the parser's
12
// precedence map. The two call sites differ only in whether the
13
// previous precedence is restored afterwards - a definition-scoped one
14
// restores, a file-scoped one holds to the end of the file.
15
class PRAGMA_PRECEDENCE is
16
_names: MutableMap[string,PRECEDENCE]
17
18
init() is
19
super.init()
20
21
_names = MAP[string,PRECEDENCE]()
22
23
_names.add("user-1", PRECEDENCE.USER_1)
24
_names.add("boolean", PRECEDENCE.BOOLEAN)
25
_names.add("user-2", PRECEDENCE.USER_2)
26
_names.add("relational", PRECEDENCE.RELATIONAL)
27
_names.add("user-3", PRECEDENCE.USER_3)
28
_names.add("range", PRECEDENCE.RANGE)
29
_names.add("user-4", PRECEDENCE.USER_4)
30
_names.add("shift", PRECEDENCE.SHIFT)
31
_names.add("user-5", PRECEDENCE.USER_5)
32
_names.add("bitwise", PRECEDENCE.BITWISE)
33
_names.add("user-6", PRECEDENCE.USER_6)
34
_names.add("addition", PRECEDENCE.ADDITION)
35
_names.add("user-7", PRECEDENCE.USER_7)
36
_names.add("multiplication", PRECEDENCE.MULTIPLICATION)
37
_names.add("user-8", PRECEDENCE.USER_8)
38
_names.add("member", PRECEDENCE.MEMBER)
39
_names.add("primary", PRECEDENCE.PRIMARY)
40
si
41
42
// Validates the pragma and sets the operator's precedence in `map`.
43
// Reports on `context` and returns false when the arguments are not
44
// a usable operator/precedence pair, leaving `map` alone; otherwise
45
// sets `operator_name` and `had_previous`, and - only when
46
// `had_previous` - `previous` to the precedence it had before.
47
apply(
48
context: CONTEXT,
49
pragma: Trees.Pragmas.PRAGMA,
50
map: MutableMap[string,PRECEDENCE],
51
operator_name: string ref,
52
previous: PRECEDENCE ref,
53
had_previous: bool ref
54
) -> bool is
55
let name = pragma.try_get_string_literal_at(0)
56
57
if !name? then
58
context.error(pragma.location, "expected operator name argument")
59
60
return false
61
fi
62
63
let precedence_name = pragma.try_get_string_literal_at(1)
64
65
if !precedence_name? then
66
context.error(pragma.location, "expected operator precedence argument")
67
68
return false
69
fi
70
71
let precedence_to_set: PRECEDENCE mut = _
72
73
if !_names.try_get_value(precedence_name, precedence_to_set ref) then
74
context.error(pragma.location, "unknown precedence name {precedence_name}")
75
76
return false
77
fi
78
79
if
80
cast int(precedence_to_set) < cast int(PRECEDENCE.USER_1) \/
81
cast int(precedence_to_set) > cast int(PRECEDENCE.USER_8)
82
then
83
context.error(pragma.location, "precedence must be between user-1 and user-8")
84
85
return false
86
fi
87
88
let previous_value: PRECEDENCE mut = _
89
let found_previous = map.try_get_value(name, previous_value ref)
90
91
map[name] = precedence_to_set
92
93
operator_name! = name
94
had_previous! = found_previous
95
previous! = previous_value
96
97
return true
98
si
99
si
100
si