moore_vhdl_syntax/lexer/
token.rs

1// Copyright (c) 2016-2021 Fabian Schuiki
2
3pub use self::DelimToken::*;
4pub use self::Token::*;
5use moore_common::name::*;
6use std;
7use std::fmt::{Display, Formatter, Result};
8
9/// A primary token as emitted by the lexer.
10#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
11pub enum Token {
12    /// A basic or extended identifier.
13    Ident(Name),
14    /// A literal.
15    Lit(Literal),
16    /// An opening delimiter.
17    OpenDelim(DelimToken),
18    /// A closing delimiter.
19    CloseDelim(DelimToken),
20    /// A keyword.
21    Keyword(Kw),
22
23    Period,
24    Comma,
25    Colon,
26    Semicolon,
27    Apostrophe,
28    Ampersand,
29    Arrow,
30    Condition,
31    LtGt,
32    VarAssign,
33    Lshift,
34    Rshift,
35    Eq,
36    Neq,
37    Lt,
38    Leq,
39    Gt,
40    Geq,
41    MatchEq,
42    MatchNeq,
43    MatchLt,
44    MatchLeq,
45    MatchGt,
46    MatchGeq,
47    Add,
48    Sub,
49    Mul,
50    Div,
51    Pow,
52    Pipe,
53    Qmark,
54
55    /// The end of the input file.
56    Eof,
57}
58
59impl Token {
60    pub fn as_str(self) -> &'static str {
61        match self {
62            Ident(_) => "identifier",
63            Lit(l) => l.as_str(),
64            OpenDelim(Paren) => "(",
65            CloseDelim(Paren) => ")",
66            OpenDelim(Brack) => "[",
67            CloseDelim(Brack) => "]",
68            Keyword(kw) => kw.as_str(),
69
70            Period => ".",
71            Comma => ",",
72            Colon => ":",
73            Semicolon => ";",
74            Apostrophe => "'",
75            Ampersand => "&",
76            Arrow => "=>",
77            Condition => "??",
78            LtGt => "<>",
79            VarAssign => ":=",
80            Lshift => "<<",
81            Rshift => ">>",
82            Eq => "=",
83            Neq => "/=",
84            Lt => "<",
85            Leq => "<=",
86            Gt => ">",
87            Geq => ">=",
88            MatchEq => "?=",
89            MatchNeq => "?/=",
90            MatchLt => "?<",
91            MatchLeq => "?<=",
92            MatchGt => "?>",
93            MatchGeq => "?>=",
94            Add => "+",
95            Sub => "-",
96            Mul => "*",
97            Div => "/",
98            Pow => "**",
99            Pipe => "|",
100            Qmark => "?",
101
102            Eof => "end of file",
103        }
104    }
105
106    /// Checks if this token is a identifier.
107    pub fn is_ident(self) -> bool {
108        match self {
109            Ident(_) => true,
110            _ => false,
111        }
112    }
113}
114
115impl Display for Token {
116    fn fmt(&self, f: &mut Formatter) -> Result {
117        match *self {
118            Ident(n) => write!(f, "identifier `{}`", n),
119            Lit(l) => write!(f, "{}", l.as_str()),
120            Keyword(kw) => write!(f, "keyword `{}`", kw.as_str()),
121            tkn => write!(f, "`{}`", tkn.as_str()),
122        }
123    }
124}
125
126#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
127pub enum Literal {
128    Abstract(
129        /// Base
130        Option<Name>,
131        /// Integer part
132        Name,
133        /// Fractional part
134        Option<Name>,
135        /// Exponent
136        Option<Exponent>,
137    ),
138    BitString(
139        /// Size
140        Option<Name>,
141        /// Base
142        BitStringBase,
143        /// Value
144        Name,
145    ),
146    Char(char),
147    String(Name),
148}
149
150impl Literal {
151    pub fn as_str(self) -> &'static str {
152        match self {
153            Literal::Abstract(..) => "abstract literal",
154            Literal::BitString(..) => "bit string literal",
155            Literal::Char(..) => "character literal",
156            Literal::String(..) => "string literal",
157        }
158    }
159}
160
161#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
162pub enum DelimToken {
163    Paren,
164    Brack,
165}
166
167#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
168pub struct Exponent(
169    /// Sign
170    pub ExponentSign,
171    /// Value
172    pub Name,
173);
174
175#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
176pub enum ExponentSign {
177    Positive,
178    Negative,
179}
180
181#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
182pub enum BitStringBase {
183    B,
184    O,
185    X,
186    D,
187    UB,
188    UO,
189    UX,
190    SB,
191    SO,
192    SX,
193}
194
195/// Generates a `Kw` enum from a list of keywords.
196macro_rules! declare_keywords {(
197    $( ($konst: ident, $string: expr) )*
198) => {
199    #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
200    pub enum Kw {
201        $($konst,)*
202    }
203
204    impl Kw {
205        pub fn as_str(self) -> &'static str {
206            match self {
207                $(Kw::$konst => $string,)*
208            }
209        }
210    }
211
212    impl std::fmt::Display for Kw {
213        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
214            write!(f, "{}", self.as_str())
215        }
216    }
217
218    pub fn find_keyword<S: AsRef<str>>(name: S) -> Option<Kw> {
219        use std::collections::HashMap;
220        use once_cell::sync::Lazy;
221        static TBL: Lazy<HashMap<&'static str, Kw>> = Lazy::new(|| {
222            let mut tbl = HashMap::new();
223            $(
224                assert!($string.chars().all(|c| !c.is_uppercase()));
225                tbl.insert($string, Kw::$konst);
226            )*
227            tbl
228        });
229        TBL.get(name.as_ref().to_lowercase().as_str()).map(|kw| *kw)
230    }
231}}
232
233declare_keywords! {
234    // Keywords as per IEEE 1076-2008 section 15.10
235    (Abs,                "abs")
236    (Access,             "access")
237    (After,              "after")
238    (Alias,              "alias")
239    (All,                "all")
240    (And,                "and")
241    (Architecture,       "architecture")
242    (Array,              "array")
243    (Assert,             "assert")
244    (Assume,             "assume")
245    (AssumeGuarantee,    "assume_guarantee")
246    (Attribute,          "attribute")
247    (Begin,              "begin")
248    (Block,              "block")
249    (Body,               "body")
250    (Buffer,             "buffer")
251    (Bus,                "bus")
252    (Case,               "case")
253    (Component,          "component")
254    (Configuration,      "configuration")
255    (Constant,           "constant")
256    (Context,            "context")
257    (Cover,              "cover")
258    (Default,            "default")
259    (Disconnect,         "disconnect")
260    (Downto,             "downto")
261    (Else,               "else")
262    (Elsif,              "elsif")
263    (End,                "end")
264    (Entity,             "entity")
265    (Exit,               "exit")
266    (Fairness,           "fairness")
267    (File,               "file")
268    (For,                "for")
269    (Force,              "force")
270    (Function,           "function")
271    (Generate,           "generate")
272    (Generic,            "generic")
273    (Group,              "group")
274    (Guarded,            "guarded")
275    (If,                 "if")
276    (Impure,             "impure")
277    (In,                 "in")
278    (Inertial,           "inertial")
279    (Inout,              "inout")
280    (Is,                 "is")
281    (Label,              "label")
282    (Library,            "library")
283    (Linkage,            "linkage")
284    (Literal,            "literal")
285    (Loop,               "loop")
286    (Map,                "map")
287    (Mod,                "mod")
288    (Nand,               "nand")
289    (New,                "new")
290    (Next,               "next")
291    (Nor,                "nor")
292    (Not,                "not")
293    (Null,               "null")
294    (Of,                 "of")
295    (On,                 "on")
296    (Open,               "open")
297    (Or,                 "or")
298    (Others,             "others")
299    (Out,                "out")
300    (Package,            "package")
301    (Parameter,          "parameter")
302    (Port,               "port")
303    (Postponed,          "postponed")
304    (Procedure,          "procedure")
305    (Process,            "process")
306    (Property,           "property")
307    (Protected,          "protected")
308    (Pure,               "pure")
309    (Range,              "range")
310    (Record,             "record")
311    (Register,           "register")
312    (Reject,             "reject")
313    (Release,            "release")
314    (Rem,                "rem")
315    (Report,             "report")
316    (Restrict,           "restrict")
317    (RestrictGuarantee,  "restrict_guarantee")
318    (Return,             "return")
319    (Rol,                "rol")
320    (Ror,                "ror")
321    (Select,             "select")
322    (Sequence,           "sequence")
323    (Severity,           "severity")
324    (Shared,             "shared")
325    (Signal,             "signal")
326    (Sla,                "sla")
327    (Sll,                "sll")
328    (Sra,                "sra")
329    (Srl,                "srl")
330    (Strong,             "strong")
331    (Subtype,            "subtype")
332    (Then,               "then")
333    (To,                 "to")
334    (Transport,          "transport")
335    (Type,               "type")
336    (Unaffected,         "unaffected")
337    (Units,              "units")
338    (Until,              "until")
339    (Use,                "use")
340    (Variable,           "variable")
341    (Vmode,              "vmode")
342    (Vprop,              "vprop")
343    (Vunit,              "vunit")
344    (Wait,               "wait")
345    (When,               "when")
346    (While,              "while")
347    (With,               "with")
348    (Xnor,               "xnor")
349    (Xor,                "xor")
350}