use lasso::Spur; use logos::Lexer; use {lasso::Rodeo, logos::Logos}; #[derive(Default)] pub struct Lextras { pub interner: Rodeo, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum IntLit { Signed(i64), Unsigned(u64), } #[derive(Logos, Copy, Clone, Debug, PartialEq, Eq)] #[logos(extras = Lextras)] #[logos(skip r"[ \t\n\f]+")] #[logos(skip r"-- .*")] #[rustfmt::skip] pub enum Token { #[token("(")] LeftParen, #[token(")")] RightParen, #[token("{")] LeftCurly, #[token("}")] RightCurly, #[token(".")] Dot, #[token(",")] Comma, #[token(":")] Colon, #[token(";")] Semicolon, #[token("_")] Underscore, #[token("←")] //____ #[token("<-")] LArrow, #[token("→")] //____ #[token("->")] RArrow, #[token(":>")] Pipe, #[token("+")] Plus, #[token("-")] Minus, #[token("*")] Star, #[token("/")] Slash, #[token("&")] And, #[token("|")] VLine, #[token("~")] Tilde, #[token("<")] Lt, #[token(">")] Gt, #[token("=")] Equ, #[token("≠") ] //__ #[token("/=")] Nequ, #[token("≤") ] //___ #[token("<=")] LtEqu, #[token("≥") ] //___, #[token(">=")] GtEqu, #[token("switch")] Switch, #[token("else")] Else, #[token("loop")] Loop, #[token("continue")] Continue, #[token("break")] Break, #[token("ret")] Ret, #[token("const")] Const, #[token("var")] Var, #[token("func")] Func, #[regex( r"\p{XID_Start}\p{XID_Continue}*", |l| l.extras.interner.get_or_intern(l.slice()) )] Ident(Spur), #[token("»", better_string)] #[regex( "\"[^\"]*\"", |l| { let slice = l.slice(); l.extras.interner.get_or_intern(&slice[1..slice.len() - 1]) } )] String(Spur), #[regex( "-?[0-9]+", |l| { Some(if let Some(slice) = l.slice().strip_prefix('-') { IntLit::Signed(slice.parse::<i64>().ok()?) } else { IntLit::Unsigned(l.slice().parse::<u64>().ok()?) }) } )] Int(IntLit), Invalid, } // For Evy, with love. fn better_string(lexer: &mut Lexer<Token>) -> Option<Spur> { let mut count = 1; for (ix, chr) in lexer.remainder().char_indices() { match chr { '«' => count -= 1, '»' => count += 1, _ => (), } if count == 0 { let slice = &lexer.remainder()[..ix]; lexer.bump(ix + '«'.len_utf8()); return Some(lexer.extras.interner.get_or_intern(slice)); } } None }