qvnt_qasm/
token.rs

1use crate::Span;
2use std::fmt;
3use std::iter::Peekable;
4
5/// Tokens returned from lexing. Represents a small amount of the source code.
6#[derive(Debug, PartialEq, Clone)]
7pub enum TokenType<'t> {
8    /// This token represents an illegal token. This is usually an error in the source code.
9    Unknown,
10
11    // Literals
12    /// Represents a Real Number
13    Real(f32),
14    /// Represents an integer
15    Int(i32),
16    /// Represents an identifier
17    Id(&'t str),
18
19    // Other Tokens
20    /// The OPENQASM statement
21    OpenQASM,
22    /// A Semicolon
23    Semicolon,
24    /// A Comma
25    Comma,
26    /// A Left Paren `(`
27    LParen,
28    /// A Left Square Paren `[`
29    LSParen,
30    /// A Left Curly Paren `{`
31    LCParen,
32    /// A Right Paren `)`
33    RParen,
34    /// A Right Square Paren `]`
35    RSParen,
36    /// A Right Curly Paren `}`
37    RCParen,
38    /// An Arrow `>`
39    Arrow,
40    /// An Equals `=`
41    Equals,
42
43    // Mathematical Expressions
44    /// Plus Sign `+`
45    Plus,
46    /// Minus Sign `-`
47    Minus,
48    /// Times Sign `*`
49    Times,
50    /// Divide Sign `/`
51    Divide,
52    /// Power Sign `^`
53    Power,
54
55    // Built In Gates
56
57    // Operators
58    /// Reserved word, `qreg`
59    QReg,
60    /// Reserved word, `creg`
61    CReg,
62    /// Reserved word, `barrier`
63    Barrier,
64    /// Reserved word, `gate`
65    Gate,
66    /// Reserved word, `measure`
67    Measure,
68    /// Reserved word, `reset`
69    Reset,
70    /// Reserved word, `include`
71    Include,
72    /// Reserved word, `opaque`
73    Opaque,
74    /// Reserved word, `if`
75    If,
76}
77
78#[derive(Debug, Clone)]
79pub struct Token<'t> {
80    pub(crate) token_type: TokenType<'t>,
81    pub(crate) span: Span,
82}
83
84impl<'t> Token<'t> {
85    pub(crate) fn to_tup(self) -> (TokenType<'t>, Span) {
86        (self.token_type, self.span)
87    }
88
89    pub fn span(&self) -> &Span {
90        &self.span
91    }
92
93    pub fn span_mut(&mut self) -> &mut Span {
94        &mut self.span
95    }
96
97    pub fn from_char(ch: char, span: Span) -> Option<Self> {
98        let token_type = match ch {
99            '=' => TokenType::Equals,
100            '+' => TokenType::Plus,
101            '-' => TokenType::Minus,
102            '*' => TokenType::Times,
103            '/' => TokenType::Divide,
104            '^' => TokenType::Power,
105            ';' => TokenType::Semicolon,
106            ',' => TokenType::Comma,
107            '(' => TokenType::LParen,
108            '[' => TokenType::LSParen,
109            '{' => TokenType::LCParen,
110            ')' => TokenType::RParen,
111            ']' => TokenType::RSParen,
112            '}' => TokenType::RCParen,
113            '>' => TokenType::Arrow,
114            _ => return None,
115        };
116
117        Some(Self { token_type, span })
118    }
119
120    pub fn lookup_ident(ident: &'t str, span: Span) -> Self {
121        let token_type = match ident {
122            "qreg" => TokenType::QReg,
123            "creg" => TokenType::CReg,
124            "barrier" => TokenType::Barrier,
125            "gate" => TokenType::Gate,
126            "measure" => TokenType::Measure,
127            "reset" => TokenType::Reset,
128            "include" => TokenType::Include,
129            "opaque" => TokenType::Opaque,
130            "if" => TokenType::If,
131            "OPENQASM" => TokenType::OpenQASM,
132            ident => TokenType::Id(ident),
133        };
134
135        Self { token_type, span }
136    }
137}
138
139impl<'t> PartialEq for Token<'t> {
140    fn eq(&self, other: &Self) -> bool {
141        self.token_type == other.token_type
142    }
143}
144
145impl<'t> From<TokenType<'t>> for Token<'t> {
146    fn from(token_type: TokenType<'t>) -> Self {
147        Self {
148            token_type,
149            span: 0..0,
150        }
151    }
152}
153
154impl<'t> Default for Token<'t> {
155    /// Choose the Illegal token as default
156    fn default() -> Self {
157        TokenType::Unknown.into()
158    }
159}
160
161#[derive(Clone)]
162pub struct TokenTree<'t, I: Iterator<Item = Token<'t>>> {
163    pub(crate) input: &'t str,
164    pub(crate) tree: Peekable<I>,
165}
166
167impl<'t, I: Iterator<Item = Token<'t>>> TokenTree<'t, I> {
168    pub fn is_empty(&self) -> bool {
169        self.input.is_empty()
170    }
171}
172
173impl<'t, 's, I, J> PartialEq<TokenTree<'s, J>> for TokenTree<'t, I>
174where
175    I: Clone + Iterator<Item = Token<'t>>,
176    J: Clone + Iterator<Item = Token<'s>>,
177{
178    fn eq(&self, other: &TokenTree<'s, J>) -> bool {
179        let mut other = other.tree.clone();
180        for a in self.tree.clone() {
181            match other.next() {
182                Some(b) if a == b => {}
183                _ => return false,
184            };
185        }
186        true
187    }
188}
189
190impl<'t, I: Clone + Iterator<Item = Token<'t>>> fmt::Debug for TokenTree<'t, I> {
191    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192        f.debug_list().entries(self.tree.clone()).finish()
193    }
194}
195
196#[test]
197fn lookup_ident_test() {
198    assert_eq!(
199        Token::lookup_ident("opaque", 0..6),
200        TokenType::Opaque.into()
201    );
202}