calc/
calc.rs

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}