wright/lexer/
identifier.rsuse super::{token::Token, token::TokenTy, Lexer};
use crate::source_tracking::fragment::Fragment;
use std::str::Chars;
use unicode_ident::{is_xid_continue, is_xid_start};
fn identifier_or_keyword(fragment: Fragment) -> TokenTy {
use TokenTy::*;
match fragment.as_str() {
"record" => KwRecord,
"type" => KwType,
"enum" => KwEnum,
"union" => KwUnion,
"func" => KwFunc,
"repr" => KwRepr,
"impl" => KwImpl,
"constraint" => KwConstraint,
"references" => KwReferences,
"trait" => KwTrait,
"const" => KwConst,
"where" => KwWhere,
"use" => KwUse,
"as" => KwAs,
"mod" => KwMod,
"if" => KwIf,
"else" => KwElse,
"match" => KwMatch,
"for" => KwFor,
"in" => KwIn,
"while" => KwWhile,
"loop" => KwLoop,
"true" => KwTrue,
"false" => KwFalse,
"_" => Underscore,
_ => Identifier,
}
}
pub fn try_consume_keyword_or_identifier(lexer: &mut Lexer) -> Option<Token> {
let mut chars: Chars = lexer.remaining.chars();
let next: char = chars.next().filter(|c| is_xid_start(*c) || *c == '_')?;
let mut bytes_consumed: usize = next.len_utf8();
bytes_consumed += chars
.take_while(|c| is_xid_continue(*c))
.map(char::len_utf8)
.sum::<usize>();
let (token_fragment, new_remaining): (Fragment, Fragment) =
lexer.remaining.split_at_unchecked(bytes_consumed);
let variant: TokenTy = identifier_or_keyword(token_fragment.clone());
lexer.remaining = new_remaining;
Some(Token {
variant,
fragment: token_fragment,
})
}
#[cfg(test)]
mod tests {
use super::{Lexer, TokenTy};
#[test]
fn identifiers_and_keywords() {
let mut lexer = Lexer::new_test("const TEST");
assert_eq!(lexer.next_token().unwrap().variant, TokenTy::KwConst);
assert_eq!(lexer.next_token().unwrap().variant, TokenTy::Whitespace);
assert_eq!(lexer.next_token().unwrap().variant, TokenTy::Identifier);
}
}