use crate::span::Span;
#[derive(Debug, Clone, PartialEq)]
pub struct Token<'a> {
pub kind: TokenKind<'a>,
pub span: Span,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TokenKind<'a> {
Ident(&'a str),
Int(i64),
Float(f64),
Str(&'a str),
InterpStr(Vec<StrPart<'a>>),
ImportPath {
path: &'a str,
version: &'a str,
},
True,
False,
Null,
Import,
As,
Type,
Enum,
Def,
End,
Domain,
New,
Assert,
Shadow,
Pub,
Cond,
Else,
Newline,
LParen,
RParen,
LBracket,
RBracket,
Colon,
Comma,
Dot,
Assign,
Arrow,
Question,
Plus,
Minus,
Star,
Slash,
Percent,
EqEq,
NotEq,
Lt,
Gt,
LtEq,
GtEq,
And,
Or,
Not,
Eof,
}
#[derive(Debug, Clone, PartialEq)]
pub enum StrPart<'a> {
Lit(&'a str),
Interp(&'a str),
}
pub const KEYWORDS: &[&str] = &[
"import", "as", "type", "enum", "def", "end", "domain", "new", "assert", "shadow", "pub",
"cond", "else", "true", "false", "null",
];
impl TokenKind<'_> {
pub(crate) fn keyword(ident: &str) -> Option<TokenKind<'static>> {
Some(match ident {
"import" => TokenKind::Import,
"as" => TokenKind::As,
"type" => TokenKind::Type,
"enum" => TokenKind::Enum,
"def" => TokenKind::Def,
"end" => TokenKind::End,
"domain" => TokenKind::Domain,
"new" => TokenKind::New,
"assert" => TokenKind::Assert,
"shadow" => TokenKind::Shadow,
"pub" => TokenKind::Pub,
"cond" => TokenKind::Cond,
"else" => TokenKind::Else,
"true" => TokenKind::True,
"false" => TokenKind::False,
"null" => TokenKind::Null,
_ => return None,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn keywords_const_matches_the_recognizer() {
for kw in KEYWORDS {
assert!(
TokenKind::keyword(kw).is_some(),
"`{kw}` is in KEYWORDS but not recognized by keyword()"
);
}
assert!(TokenKind::keyword("text").is_none(), "text is contextual");
assert!(TokenKind::keyword("nope").is_none());
}
}