Appearance
| 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 |