1
Fork 0

Make TokenType::from_u32 foolproof.

Currently it relies on having the right integer for every variant, and
if you add a variant you need to adjust the integers for all subsequent
variants, which is a pain.

This commit introduces a match guard formulation that takes advantage of
the enum-to-integer conversion to avoid specifying the integer for each
variant. And it does this via a macro to avoid lots of boilerplate.
This commit is contained in:
Nicholas Nethercote 2024-12-06 11:05:42 +11:00
parent b9bf0b4b10
commit df56c50cee

View file

@ -145,124 +145,135 @@ pub enum TokenType {
// tidy-alphabetical-end // tidy-alphabetical-end
} }
// Macro to avoid repetitive boilerplate code.
macro_rules! from_u32_match {
($val:ident; $($tok:ident,)+) => {
// A more obvious formulation would be `0 => TokenType::Eq`. But
// this formulation with the guard lets us avoid specifying a
// specific integer for each variant.
match $val {
$(
t if t == TokenType::$tok as u32 => TokenType::$tok,
)+
_ => panic!("unhandled value: {}", $val),
}
};
}
impl TokenType { impl TokenType {
fn from_u32(val: u32) -> TokenType { fn from_u32(val: u32) -> TokenType {
let token_type = match val { let token_type = from_u32_match! { val;
0 => TokenType::Eq, Eq,
1 => TokenType::Lt, Lt,
2 => TokenType::Le, Le,
3 => TokenType::EqEq, EqEq,
4 => TokenType::Gt, Gt,
5 => TokenType::AndAnd, AndAnd,
6 => TokenType::OrOr, OrOr,
7 => TokenType::Not, Not,
8 => TokenType::Tilde, Tilde,
9 => TokenType::Plus, Plus,
10 => TokenType::Minus, Minus,
11 => TokenType::Star, Star,
12 => TokenType::And, And,
13 => TokenType::Or, Or,
14 => TokenType::At, At,
15 => TokenType::Dot, Dot,
16 => TokenType::DotDot, DotDot,
17 => TokenType::DotDotDot, DotDotDot,
18 => TokenType::DotDotEq, DotDotEq,
19 => TokenType::Comma, Comma,
20 => TokenType::Semi, Semi,
21 => TokenType::Colon, Colon,
22 => TokenType::PathSep, PathSep,
23 => TokenType::RArrow, RArrow,
24 => TokenType::FatArrow, FatArrow,
25 => TokenType::Pound, Pound,
26 => TokenType::Question, Question,
27 => TokenType::OpenParen, OpenParen,
28 => TokenType::CloseParen, CloseParen,
29 => TokenType::OpenBrace, OpenBrace,
30 => TokenType::CloseBrace, CloseBrace,
31 => TokenType::OpenBracket, OpenBracket,
32 => TokenType::CloseBracket, CloseBracket,
33 => TokenType::Eof, Eof,
34 => TokenType::Operator, Operator,
35 => TokenType::Ident, Ident,
36 => TokenType::Lifetime, Lifetime,
37 => TokenType::Path, Path,
38 => TokenType::Type, Type,
39 => TokenType::Const, Const,
40 => TokenType::KwAs, KwAs,
41 => TokenType::KwAsync, KwAsync,
42 => TokenType::KwAuto, KwAuto,
43 => TokenType::KwAwait, KwAwait,
44 => TokenType::KwBecome, KwBecome,
45 => TokenType::KwBox, KwBox,
46 => TokenType::KwBreak, KwBreak,
47 => TokenType::KwCatch, KwCatch,
48 => TokenType::KwConst, KwConst,
49 => TokenType::KwContinue, KwContinue,
50 => TokenType::KwCrate, KwCrate,
51 => TokenType::KwDefault, KwDefault,
52 => TokenType::KwDyn, KwDyn,
53 => TokenType::KwElse, KwElse,
54 => TokenType::KwEnum, KwEnum,
55 => TokenType::KwExtern, KwExtern,
56 => TokenType::KwFn, KwFn,
57 => TokenType::KwFor, KwFor,
58 => TokenType::KwGen, KwGen,
59 => TokenType::KwIf, KwIf,
60 => TokenType::KwImpl, KwImpl,
61 => TokenType::KwIn, KwIn,
62 => TokenType::KwLet, KwLet,
63 => TokenType::KwLoop, KwLoop,
64 => TokenType::KwMacro, KwMacro,
65 => TokenType::KwMacroRules, KwMacroRules,
66 => TokenType::KwMatch, KwMatch,
67 => TokenType::KwMod, KwMod,
68 => TokenType::KwMove, KwMove,
69 => TokenType::KwMut, KwMut,
70 => TokenType::KwPub, KwPub,
71 => TokenType::KwRaw, KwRaw,
72 => TokenType::KwRef, KwRef,
73 => TokenType::KwReturn, KwReturn,
74 => TokenType::KwReuse, KwReuse,
75 => TokenType::KwSafe, KwSafe,
76 => TokenType::KwSelfUpper, KwSelfUpper,
77 => TokenType::KwStatic, KwStatic,
78 => TokenType::KwStruct, KwStruct,
79 => TokenType::KwTrait, KwTrait,
80 => TokenType::KwTry, KwTry,
81 => TokenType::KwType, KwType,
82 => TokenType::KwUnderscore, KwUnderscore,
83 => TokenType::KwUnsafe, KwUnsafe,
84 => TokenType::KwUse, KwUse,
85 => TokenType::KwWhere, KwWhere,
86 => TokenType::KwWhile, KwWhile,
87 => TokenType::KwYield, KwYield,
88 => TokenType::SymAttSyntax, SymAttSyntax,
89 => TokenType::SymClobberAbi, SymClobberAbi,
90 => TokenType::SymInlateout, SymInlateout,
91 => TokenType::SymInout, SymInout,
92 => TokenType::SymIs, SymIs,
93 => TokenType::SymLabel, SymLabel,
94 => TokenType::SymLateout, SymLateout,
95 => TokenType::SymMayUnwind, SymMayUnwind,
96 => TokenType::SymNomem, SymNomem,
97 => TokenType::SymNoreturn, SymNoreturn,
98 => TokenType::SymNostack, SymNostack,
99 => TokenType::SymOptions, SymOptions,
100 => TokenType::SymOut, SymOut,
101 => TokenType::SymPreservesFlags, SymPreservesFlags,
102 => TokenType::SymPure, SymPure,
103 => TokenType::SymReadonly, SymReadonly,
104 => TokenType::SymSym, SymSym,
_ => panic!("unhandled value: {val}"),
}; };
// This assertion will detect if this method and the type definition get out of sync.
assert_eq!(token_type as u32, val);
token_type token_type
} }