1use logos::Logos;
2
3pub use logos::Span;
4
5#[derive(Logos, Debug, Clone, PartialEq, Eq)]
7#[logos(error = LexError)]
8#[logos(skip r"[ \t\r\n]+")]
9pub enum PtxToken {
10 #[regex(r"//[^\n]*", logos::skip)]
11 #[regex(r"/\*[^*]*\*+(?:[^/*][^*]*\*+)*/", logos::skip)]
12 #[token("::")]
13 DoubleColon,
14 #[token(".")]
15 Dot,
16 #[token(",")]
17 Comma,
18 #[token(";")]
19 Semicolon,
20 #[token(":")]
21 Colon,
22 #[token("(")]
23 LParen,
24 #[token(")")]
25 RParen,
26 #[token("[")]
27 LBracket,
28 #[token("]")]
29 RBracket,
30 #[token("{")]
31 LBrace,
32 #[token("}")]
33 RBrace,
34 #[token("+")]
35 Plus,
36 #[token("-")]
37 Minus,
38 #[token("*")]
39 Star,
40 #[token("/")]
41 Slash,
42 #[token("<")]
43 LAngle,
44 #[token(">")]
45 RAngle,
46 #[token("=")]
47 Equals,
48 #[token("%")]
49 Percent,
50 #[token("!")]
51 Exclaim,
52 #[token("|")]
53 Pipe,
54 #[token("&")]
55 Ampersand,
56 #[token("^")]
57 Caret,
58 #[token("~")]
59 Tilde,
60 #[token("@")]
61 At,
62 #[regex(r"0[fFdD][0-9a-fA-F]{8}", |lex| lex.slice().to_string())]
63 #[regex(r"0[fFdD][0-9a-fA-F]{16}", |lex| lex.slice().to_string())]
64 HexFloat(String),
65 #[regex(r"0[xX][0-9a-fA-F]+", |lex| lex.slice().to_string())]
66 HexInteger(String),
67 #[regex(r"0[bB][01]+", |lex| lex.slice().to_string())]
68 BinaryInteger(String),
69 #[regex(r"0[0-7]+", |lex| lex.slice().to_string())]
70 OctalInteger(String),
71 #[regex(r"[0-9]+\.[0-9]+[eE][+-]?[0-9]+", |lex| lex.slice().to_string())]
72 #[regex(r"[0-9]+[eE][+-]?[0-9]+", |lex| lex.slice().to_string())]
73 FloatExponent(String),
74 #[regex(r"[0-9]+\.[0-9]+", |lex| lex.slice().to_string())]
75 Float(String),
76 #[regex(r"[0-9]+", |lex| lex.slice().to_string())]
77 DecimalInteger(String),
78 #[regex(r"%[a-zA-Z_][a-zA-Z0-9_]*", |lex| lex.slice().to_string())]
79 Register(String),
80 #[regex(r"[a-zA-Z_$][a-zA-Z0-9_$-]*", |lex| lex.slice().to_string())]
81 Identifier(String),
82 #[regex(r#""([^"\\]|\\.)*""#, |lex| {
83 let slice = lex.slice();
84 slice[1..slice.len() - 1].to_string()
85 })]
86 StringLiteral(String),
87}
88
89impl PtxToken {
90 pub fn as_str(&self) -> &str {
92 match self {
93 PtxToken::Identifier(s) |
94 PtxToken::DecimalInteger(s) |
95 PtxToken::HexInteger(s) |
96 PtxToken::BinaryInteger(s) |
97 PtxToken::OctalInteger(s) |
98 PtxToken::Float(s) |
99 PtxToken::FloatExponent(s) |
100 PtxToken::HexFloat(s) |
101 PtxToken::Register(s) |
102 PtxToken::StringLiteral(s) => s.as_str(),
103 _ => "",
104 }
105 }
106}
107
108#[derive(Debug, Clone, PartialEq, Default)]
109pub struct LexError {
110 pub span: Span,
111}
112
113impl From<Span> for LexError {
114 fn from(span: Span) -> Self {
115 LexError { span }
116 }
117}
118
119pub fn tokenize(source: &str) -> Result<Vec<(PtxToken, Span)>, LexError> {
120 let mut lexer = PtxToken::lexer(source);
121 let mut tokens = Vec::new();
122
123 while let Some(item) = lexer.next() {
124 match item {
125 Ok(token) => tokens.push((token, lexer.span())),
126 Err(_) => return Err(LexError { span: lexer.span() }),
127 }
128 }
129
130 Ok(tokens)
131}