blues-lsp 0.1.0

LSP language server for the Bluespec SystemVerilog language
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
use std::fmt::Display;

use arcstr::Substr;

use crate::syntax::location::Span;

#[derive(Debug, Clone)]
pub struct Token {
    pub span: Span,
    pub kind: TokenKind,
}

#[derive(Debug, Clone)]
pub enum TokenKind {
    /// Keywords
    Kw(Kw),
    /// Identifiers
    Ident(Substr),
    /// System identifiers ('$foo')
    SysIdent(Substr),
    /// Symbols
    Sym(Sym),
    /// Numeric literals
    Num(NumLit),
    /// String literals
    Str(Substr),
    // Note: we don't really have a need to represent the actual values, yet.
    /// Comments
    Comment,
    /// Error placeholder
    Error,
}

impl TokenKind {
    pub fn significant(&self) -> bool {
        !matches!(self, TokenKind::Comment | TokenKind::Error)
    }

    pub fn ident(&self) -> Option<&Substr> {
        match self {
            TokenKind::Ident(substr) => Some(substr),
            _ => None,
        }
    }
}

impl Display for TokenKind {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            TokenKind::Kw(kw) => write!(f, "keyword '{kw}'"),
            TokenKind::Ident(ident) => write!(f, "identifier '{ident}'"),
            TokenKind::SysIdent(ident) => write!(f, "system identifier '{ident}'"),
            TokenKind::Sym(sym) => write!(f, "symbol '{sym}'"),
            TokenKind::Num(NumLit::Int) => write!(f, "integer number"),
            TokenKind::Num(NumLit::Mixed) => write!(f, "mixed number"),
            TokenKind::Num(NumLit::Real) => write!(f, "real number"),
            TokenKind::Num(NumLit::Repeated) => write!(f, "repeated bit number"),
            TokenKind::Str(_) => write!(f, "string"),
            TokenKind::Comment => write!(f, "comment"),
            TokenKind::Error => write!(f, "error token"),
        }
    }
}

macro_rules! kw_list {
    ($(($name:ident, $string:literal, $doc:literal),)*) => {
        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
        pub enum Kw {
            $(#[doc=$doc] $name,)*
            __Last
        }

        const KWS: &[(Kw, &'static str)]= &[
            $((Kw::$name, $string),)*
        ];

        impl Display for Kw {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                match self {
                    $(Kw::$name => f.write_str($string),)*
                    Kw::__Last => unreachable!()
                }
            }
        }
    };
}

impl Kw {
    pub fn parse(s: &str) -> Option<Kw> {
        // TODO: this could do with a trie or smth
        KWS.iter().find(|k| k.1 == s).map(|k| k.0)
    }
}

// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogKeywords.lhs#L379
// BSV keywords moved to front.
#[rustfmt::skip]
kw_list![
    (Action,                 "action",                  "`action`"),
    (Endaction,              "endaction",               "`endaction`"),
    (Actionvalue,            "actionvalue",             "`actionvalue`"),
    (Endactionvalue,         "endactionvalue",          "`endactionvalue`"),
    (Deriving,               "deriving",                "`deriving`"),
    (Endinstance,            "endinstance",             "`endinstance`"),
    (Let,                    "let",                     "`let`"),
    (Method,                 "method",                  "`method`"),
    (Endmethod,              "endmethod",               "`endmethod`"),
    (Par,                    "par",                     "`par`"),
    (Endpar,                 "endpar",                  "`endpar`"),
    (Abortif,                "abortif",                 "`abortif`"),
    (Provisos,               "provisos",                "`provisos`"),
    (Rule,                   "rule",                    "`rule`"),
    (Endrule,                "endrule",                 "`endrule`"),
    (Rules,                  "rules",                   "`rules`"),
    (Endrules,               "endrules",                "`endrules`"),
    (Seq,                    "seq",                     "`seq`"),
    (Endseq,                 "endseq",                  "`endseq`"),
    (Goto,                   "goto",                    "`goto`"),
    (Typeclass,              "typeclass",               "`typeclass`"),
    (Endtypeclass,           "endtypeclass",            "`endtypeclass`"),
    (Valueof,                "valueof",                 "`valueof`"),
    (ValueOf,                "valueOf",                 "`valueOf`"),
    (Stringof,               "stringof",                "`stringof`"),
    (StringOf,               "stringOf",                "`stringOf`"),
    (ClockedBy,              "clocked_by",              "`clocked_by`"),
    (ResetBy,                "reset_by",                "`reset_by`"),
    (PoweredBy,              "powered_by",              "`powered_by`"),
    (ActionType,             "Action",                  "`Action`"),
    (ActionValueType,        "ActionValue",             "`ActionValue`"),
    (Alias,                  "alias",                   "`alias`"),
    (Always,                 "always",                  "`always`"),
    (AlwaysComb,             "always_comb",             "`always_comb`"),
    (AlwaysFf,               "always_ff",               "`always_ff`"),
    (AlwaysLatch,            "always_latch",            "`always_latch`"),
    (And,                    "and",                     "`and`"),
    (Assert,                 "assert",                  "`assert`"),
    (AssertStrobe,           "assert_strobe",           "`assert_strobe`"),
    (Assign,                 "assign",                  "`assign`"),
    (Assume,                 "assume",                  "`assume`"),
    (Automatic,              "automatic",               "`automatic`"),
    (Before,                 "before",                  "`before`"),
    (Begin,                  "begin",                   "`begin`"),
    (Bind,                   "bind",                    "`bind`"),
    (Bins,                   "bins",                    "`bins`"),
    (Binsof,                 "binsof",                  "`binsof`"),
    (Bit,                    "bit",                     "`bit`"),
    (Break,                  "break",                   "`break`"),
    (Buf,                    "buf",                     "`buf`"),
    (Bufif0,                 "bufif0",                  "`bufif0`"),
    (Bufif1,                 "bufif1",                  "`bufif1`"),
    (Byte,                   "byte",                    "`byte`"),
    (Case,                   "case",                    "`case`"),
    (Casex,                  "casex",                   "`casex`"),
    (Casez,                  "casez",                   "`casez`"),
    (Cell,                   "cell",                    "`cell`"),
    (Chandle,                "chandle",                 "`chandle`"),
    (Class,                  "class",                   "`class`"),
    (Clocking,               "clocking",                "`clocking`"),
    (Cmos,                   "cmos",                    "`cmos`"),
    (Config,                 "config",                  "`config`"),
    (Const,                  "const",                   "`const`"),
    (Constraint,             "constraint",              "`constraint`"),
    (Context,                "context",                 "`context`"),
    (Continue,               "continue",                "`continue`"),
    (Cover,                  "cover",                   "`cover`"),
    (Covergroup,             "covergroup",              "`covergroup`"),
    (Coverpoint,             "coverpoint",              "`coverpoint`"),
    (Cross,                  "cross",                   "`cross`"),
    (Deassign,               "deassign",                "`deassign`"),
    (Default,                "default",                 "`default`"),
    (Defparam,               "defparam",                "`defparam`"),
    (Design,                 "design",                  "`design`"),
    (Disable,                "disable",                 "`disable`"),
    (Dist,                   "dist",                    "`dist`"),
    (Do,                     "do",                      "`do`"),
    (Edge,                   "edge",                    "`edge`"),
    (Else,                   "else",                    "`else`"),
    (End,                    "end",                     "`end`"),
    (Endcase,                "endcase",                 "`endcase`"),
    (Endclass,               "endclass",                "`endclass`"),
    (Endclocking,            "endclocking",             "`endclocking`"),
    (Endconfig,              "endconfig",               "`endconfig`"),
    (Endfunction,            "endfunction",             "`endfunction`"),
    (Endgenerate,            "endgenerate",             "`endgenerate`"),
    (Endgroup,               "endgroup",                "`endgroup`"),
    (Endinterface,           "endinterface",            "`endinterface`"),
    (Endmodule,              "endmodule",               "`endmodule`"),
    (Endpackage,             "endpackage",              "`endpackage`"),
    (Endprimitive,           "endprimitive",            "`endprimitive`"),
    (Endprogram,             "endprogram",              "`endprogram`"),
    (Endproperty,            "endproperty",             "`endproperty`"),
    (Endspecify,             "endspecify",              "`endspecify`"),
    (Endsequence,            "endsequence",             "`endsequence`"),
    (Endtable,               "endtable",                "`endtable`"),
    (Endtask,                "endtask",                 "`endtask`"),
    (Enum,                   "enum",                    "`enum`"),
    (Event,                  "event",                   "`event`"),
    (Expect,                 "expect",                  "`expect`"),
    (Export,                 "export",                  "`export`"),
    (Extends,                "extends",                 "`extends`"),
    (Extern,                 "extern",                  "`extern`"),
    (Final,                  "final",                   "`final`"),
    (FirstMatch,             "first_match",             "`first_match`"),
    (For,                    "for",                     "`for`"),
    (Force,                  "force",                   "`force`"),
    (Foreach,                "foreach",                 "`foreach`"),
    (Forever,                "forever",                 "`forever`"),
    (Fork,                   "fork",                    "`fork`"),
    (Forkjoin,               "forkjoin",                "`forkjoin`"),
    (Function,               "function",                "`function`"),
    (Generate,               "generate",                "`generate`"),
    (Genvar,                 "genvar",                  "`genvar`"),
    (Highz0,                 "highz0",                  "`highz0`"),
    (Highz1,                 "highz1",                  "`highz1`"),
    (If,                     "if",                      "`if`"),
    (Iff,                    "iff",                     "`iff`"),
    (Ifnone,                 "ifnone",                  "`ifnone`"),
    (IgnoreBins,             "ignore_bins",             "`ignore_bins`"),
    (IllegalBins,            "illegal_bins",            "`illegal_bins`"),
    (Import,                 "import",                  "`import`"),
    (Incdir,                 "incdir",                  "`incdir`"),
    (Include,                "include",                 "`include`"),
    (Initial,                "initial",                 "`initial`"),
    (Inout,                  "inout",                   "`inout`"),
    (Input,                  "input",                   "`input`"),
    (Inside,                 "inside",                  "`inside`"),
    (Instance,               "instance",                "`instance`"),
    (Int,                    "int",                     "`int`"),
    (Integer,                "integer",                 "`integer`"),
    (Interface,              "interface",               "`interface`"),
    (Intersect,              "intersect",               "`intersect`"),
    (Join,                   "join",                    "`join`"),
    (JoinAny,                "join_any",                "`join_any`"),
    (JoinNone,               "join_none",               "`join_none`"),
    (Large,                  "large",                   "`large`"),
    (Liblist,                "liblist",                 "`liblist`"),
    (Library,                "library",                 "`library`"),
    (Local,                  "local",                   "`local`"),
    (Localparam,             "localparam",              "`localparam`"),
    (Logic,                  "logic",                   "`logic`"),
    (Longint,                "longint",                 "`longint`"),
    (Macromodule,            "macromodule",             "`macromodule`"),
    (Match,                  "match",                   "`match`"),
    (Matches,                "matches",                 "`matches`"),
    (Medium,                 "medium",                  "`medium`"),
    (Modport,                "modport",                 "`modport`"),
    (Module,                 "module",                  "`module`"),
    (Nand,                   "nand",                    "`nand`"),
    (Negedge,                "negedge",                 "`negedge`"),
    (New,                    "new",                     "`new`"),
    (Nmos,                   "nmos",                    "`nmos`"),
    (Nor,                    "nor",                     "`nor`"),
    (Noshowcancelled,        "noshowcancelled",         "`noshowcancelled`"),
    (Not,                    "not",                     "`not`"),
    (Notif0,                 "notif0",                  "`notif0`"),
    (Notif1,                 "notif1",                  "`notif1`"),
    (Null,                   "null",                    "`null`"),
    (Or,                     "or",                      "`or`"),
    (Output,                 "output",                  "`output`"),
    (Package,                "package",                 "`package`"),
    (Packed,                 "packed",                  "`packed`"),
    (Parameter,              "parameter",               "`parameter`"),
    (Pmos,                   "pmos",                    "`pmos`"),
    (Posedge,                "posedge",                 "`posedge`"),
    (Primitive,              "primitive",               "`primitive`"),
    (Priority,               "priority",                "`priority`"),
    (Program,                "program",                 "`program`"),
    (Property,               "property",                "`property`"),
    (Protected,              "protected",               "`protected`"),
    (Pull0,                  "pull0",                   "`pull0`"),
    (Pull1,                  "pull1",                   "`pull1`"),
    (Pulldown,               "pulldown",                "`pulldown`"),
    (Pullup,                 "pullup",                  "`pullup`"),
    (PulsestyleOnevent,      "pulsestyle_onevent",      "`pulsestyle_onevent`"),
    (PulsestyleOndetect,     "pulsestyle_ondetect",     "`pulsestyle_ondetect`"),
    (Pure,                   "pure",                    "`pure`"),
    (Rand,                   "rand",                    "`rand`"),
    (Randc,                  "randc",                   "`randc`"),
    (Randcase,               "randcase",                "`randcase`"),
    (Randsequence,           "randsequence",            "`randsequence`"),
    (Rcmos,                  "rcmos",                   "`rcmos`"),
    (Real,                   "real",                    "`real`"),
    (Realtime,               "realtime",                "`realtime`"),
    (Ref,                    "ref",                     "`ref`"),
    (Reg,                    "reg",                     "`reg`"),
    (Release,                "release",                 "`release`"),
    (Repeat,                 "repeat",                  "`repeat`"),
    (Return,                 "return",                  "`return`"),
    (Rnmos,                  "rnmos",                   "`rnmos`"),
    (Rpmos,                  "rpmos",                   "`rpmos`"),
    (Rtran,                  "rtran",                   "`rtran`"),
    (Rtranif0,               "rtranif0",                "`rtranif0`"),
    (Rtranif1,               "rtranif1",                "`rtranif1`"),
    (Scalared,               "scalared",                "`scalared`"),
    (Sequence,               "sequence",                "`sequence`"),
    (Shortint,               "shortint",                "`shortint`"),
    (Shortreal,              "shortreal",               "`shortreal`"),
    (Showcancelled,          "showcancelled",           "`showcancelled`"),
    (Signed,                 "signed",                  "`signed`"),
    (Small,                  "small",                   "`small`"),
    (Solve,                  "solve",                   "`solve`"),
    (Specify,                "specify",                 "`specify`"),
    (Specparam,              "specparam",               "`specparam`"),
    (Static,                 "static",                  "`static`"),
    (String,                 "string",                  "`string`"),
    (Strong0,                "strong0",                 "`strong0`"),
    (Strong1,                "strong1",                 "`strong1`"),
    (Struct,                 "struct",                  "`struct`"),
    (Super,                  "super",                   "`super`"),
    (Supply0,                "supply0",                 "`supply0`"),
    (Supply1,                "supply1",                 "`supply1`"),
    (Table,                  "table",                   "`table`"),
    (Tagged,                 "tagged",                  "`tagged`"),
    (Task,                   "task",                    "`task`"),
    (This,                   "this",                    "`this`"),
    (Throughout,             "throughout",              "`throughout`"),
    (Time,                   "time",                    "`time`"),
    (Timeprecision,          "timeprecision",           "`timeprecision`"),
    (Timeunit,               "timeunit",                "`timeunit`"),
    (Tran,                   "tran",                    "`tran`"),
    (Tranif0,                "tranif0",                 "`tranif0`"),
    (Tranif1,                "tranif1",                 "`tranif1`"),
    (Tri,                    "tri",                     "`tri`"),
    (Tri0,                   "tri0",                    "`tri0`"),
    (Tri1,                   "tri1",                    "`tri1`"),
    (Triand,                 "triand",                  "`triand`"),
    (Trior,                  "trior",                   "`trior`"),
    (Trireg,                 "trireg",                  "`trireg`"),
    (Type,                   "type",                    "`type`"),
    (Typedef,                "typedef",                 "`typedef`"),
    (Union,                  "union",                   "`union`"),
    (Unique,                 "unique",                  "`unique`"),
    (Unsigned,               "unsigned",                "`unsigned`"),
    (Use,                    "use",                     "`use`"),
    (Var,                    "var",                     "`var`"),
    (Vectored,               "vectored",                "`vectored`"),
    (Virtual,                "virtual",                 "`virtual`"),
    (Void,                   "void",                    "`void`"),
    (Wait,                   "wait",                    "`wait`"),
    (WaitOrder,              "wait_order",              "`wait_order`"),
    (Wand,                   "wand",                    "`wand`"),
    (Weak0,                  "weak0",                   "`weak0`"),
    (Weak1,                  "weak1",                   "`weak1`"),
    (While,                  "while",                   "`while`"),
    (Wildcard,               "wildcard",                "`wildcard`"),
    (Wire,                   "wire",                    "`wire`"),
    (With,                   "with",                    "`with`"),
    (Within,                 "within",                  "`within`"),
    (Wor,                    "wor",                     "`wor`"),
    (Xnor,                   "xnor",                    "`xnor`"),
    (Xor,                    "xor",                     "`xor`"),
];

macro_rules! sym_list {
    ($(($name:ident, $string:literal, $doc:literal),)*) => {
        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
        pub enum Sym {
            $(#[doc=$doc] $name,)*
        }

        const SYMS: &[(Sym, &'static str)]= &[
            $((Sym::$name, $string),)*
        ];

        impl Display for Sym {
            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                match self {
                    $(Sym::$name => f.write_str($string),)*
                }
            }
        }
    };
}

impl Sym {
    pub fn longest_match(str: &str) -> Option<(Sym, &'static str)> {
        // SYMS are sorted by length descending, so first match is guaranteed to be the longest.
        SYMS.iter().find(|(_, sym)| str.starts_with(sym)).copied()
    }
}

// https://github.com/B-Lang-org/bsc/blob/a798d8a94d54197d2b4755afdbb460cdc559c151/src/comp/SystemVerilogKeywords.lhs#L642
// *MUST* be sorted by length descending
#[rustfmt::skip]
sym_list![
    ( LtLtLtEq,           "<<<=",      "`<<<=`" ),
    ( GtGtGtEq,           ">>>=",      "`>>>=`" ),
    ( BangEqEq,           "!==",       "`!==`"  ),
    ( BangQuestionEq,     "!?=",       "`!?=`"  ),
    ( EtEtEt,             "&&&",       "`&&&`"  ),
    ( LtLtLt,             "<<<",       "`<<<`"  ),
    ( LtLtEq,             "<<=",       "`<<=`"  ),
    ( EqEqEq,             "===",       "`===`"  ),
    ( EqQuestionEq,       "=?=",       "`=?=`"  ),
    ( GtGtEq,             ">>=",       "`>>=`"  ),
    ( GtGtGt,             ">>>",       "`>>>`"  ),
    ( LbracketMinusGt,    "[->",       "`[->`"  ),
    ( PipeMinusGt,        "|->",       "`|->`"  ),
    ( PipeEqGt,           "|=>",       "`|=>`"  ),
    ( BangEq,             "!=",        "`!=`"   ),
    ( HashHash,           "##",        "`##`"   ),
    ( PercentEq,          "%=",        "`%=`"   ),
    ( EtEt,               "&&",        "`&&`"   ),
    ( EtEq,               "&=",        "`&=`"   ),
    ( LparenStar,         "(*",        "`(*`"   ),
    ( StarRparen,         "*)",        "`*)`"   ),
    ( StarStar,           "**",        "`**`"   ),
    ( PlusPlus,           "++",        "`++`"   ),
    ( PlusEq,             "+=",        "`+=`"   ),
    ( MinusMinus,         "--",        "`--`"   ),
    ( MinusEq,            "-=",        "`-=`"   ),
    ( MinusGt,            "->",        "`->`"   ),
    ( DotStar,            ".*",        "`.*`"   ),
    ( DotDot,             "..",        "`..`"   ),
    ( SlashEq,            "/=",        "`/=`"   ),
    ( ColonColon,         "::",        "`::`"   ),
    ( LtMinus,            "<-",        "`<-`"   ),
    ( LtLt,               "<<",        "`<<`"   ),
    ( LtEq,               "<=",        "`<=`"   ),
    ( LtGt,               "<>",        "`<>`"   ),
    ( EqEq,               "==",        "`==`"   ),
    ( GtEq,               ">=",        "`>=`"   ),
    ( GtGt,               ">>",        "`>>`"   ),
    ( LbracketStar,       "[*",        "`[*`"   ),
    ( LbracketEq,         "[=",        "`[=`"   ),
    ( CaretEq,            "^=",        "`^=`"   ),
    ( CaretTilde,         "^~",        "`^~`"   ),
    ( PipeEq,             "|=",        "`|=`"   ),
    ( PipePipe,           "||",        "`||`"   ),
    ( TildeEt,            "~&",        "`~&`"   ),
    ( TildeCaret,         "~^",        "`~^`"   ),
    ( TildePipe,          "~|",        "`~|`"   ),
    ( Bang,               "!",         "`!`"    ),
    ( Hash,               "#",         "`#`"    ),
    ( Dollar,             "$",         "`$`"    ),
    ( Percent,            "%",         "`%`"    ),
    ( Et,                 "&",         "`&`"    ),
    ( Tick,               "'",         "`'`"    ),
    ( Lparen,             "(",         "`(`"    ),
    ( Rparen,             ")",         "`)`"    ),
    ( Star,               "*",         "`*`"    ),
    ( Plus,               "+",         "`+`"    ),
    ( Comma,              ",",         "`,`"    ),
    ( Minus,              "-",         "`-`"    ),
    ( Dot,                ".",         "`.`"    ),
    ( Slash,              "/",         "`/`"    ),
    ( Colon,              ":",         "`:`"    ),
    ( Semi,               ";",         "`;`"    ),
    ( Lt,                 "<",         "`<`"    ),
    ( Eq,                 "=",         "`=`"    ),
    ( Gt,                 ">",         "`>`"    ),
    ( Question,           "?",         "`?`"    ),
    ( Lbracket,           "[",         "`[`"    ),
    ( Rbracket,           "]",         "`]`"    ),
    ( Caret,              "^",         "`^`"    ),
    ( Backtick,           "`",         "```"    ),
    ( Lbrace,             "{",         "`{`"    ),
    ( Pipe,               "|",         "`|`"    ),
    ( Rbrace,             "}",         "`}`"    ),
    ( Tilde,              "~",         "`~`"    ),
];

/// Numeric literal
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NumLit {
    /// Integer
    Int,
    /// Real (64-bit IEEE)
    Real,
    /// Repeated bit pattern
    Repeated,
    /// Mixed, includes 'X' and 'Z' bits
    Mixed,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Bit {
    Zero,
    One,
    Undef,
    HighZ,
    DontCare,
}

impl Bit {
    pub fn parse(c: char) -> Option<Self> {
        match c {
            '0' => Some(Self::Zero),
            '1' => Some(Self::One),
            'x' | 'X' => Some(Self::Undef),
            'z' | 'Z' => Some(Self::HighZ),
            '?' => Some(Self::DontCare),
            _ => None,
        }
    }
}