1use generic_lexer::{Lexer, BufferedInput, MatchError};
2
3#[derive(Debug)]
4enum TokenKind {
5 Int, Float,
6 Name,
7 Plus, Minus, Star, Slash, Semicolon, Equals,
8}
9
10fn lex_int(input: &mut BufferedInput) -> TokenKind {
11 input.accept_while(char::is_ascii_digit);
12 if let Some(_) = input.accept_if(|c| *c == '.') {
13 return lex_float(input);
14 }
15 TokenKind::Int
16}
17
18fn lex_float(input: &mut BufferedInput) -> TokenKind {
19 input.accept_while(char::is_ascii_digit);
20 TokenKind::Float
21}
22
23fn lex_name(input: &mut BufferedInput) -> TokenKind {
24 input.accept_while(|c| *c == '_' || c.is_ascii_alphabetic());
25 TokenKind::Name
26}
27
28fn lex(first_char: char, input: &mut BufferedInput) -> Result<TokenKind, MatchError> {
29 let kind = match first_char {
30 '+' => TokenKind::Plus,
31 '-' => TokenKind::Minus,
32 '*' => TokenKind::Star,
33 '/' => TokenKind::Slash,
34 ';' => TokenKind::Semicolon,
35 '=' => TokenKind::Equals,
36
37 c if c.is_ascii_digit() => lex_int(input),
38 c if c.is_ascii_alphabetic() => lex_name(input),
39
40 c => return Err(MatchError::Unexpected(c))
41 };
42
43 Ok(kind)
44}
45
46fn main() -> Result<(), Box<dyn std::error::Error>> {
47 let input = "a = 420 + 69 * 3.14;";
48 let lexer = Lexer::new(&input, &lex, true);
49 let tokens = lexer.collect::<Result<Vec<_>, _>>()?;
50 println!("{:#?}", tokens);
51 Ok(())
52}