use token_iter::*;
#[derive(Clone, Debug, PartialEq)]
#[rustfmt::skip]
enum Token {
LT, LE, GT, GE, EqEq, EQ, LCurly, RCurly, While, If,
Identifier(String), Int(u64), BadInt(String), Unrecognized(char)
}
#[rustfmt::skip]
fn tokenizer(lx: &mut Lexer) -> Option<Token> {
use Token::*;
let is_digit = |c| char::is_ascii_digit(&c);
Some(
match lx.skip_while(char::is_whitespace).next()? {
'<' => if lx.at('=') {LE} else {LT},
'>' => if lx.at('=') {GE} else {GT},
'=' => if lx.at('=') {EqEq} else {EQ},
'{' => LCurly,
'}' => RCurly,
c if c.is_alphabetic() =>
match lx.take_while(char::is_alphanumeric).get() {
"while" => While,
"if" => If,
s => Identifier(s.into())
},
c if is_digit(c) =>
lx.take_while(is_digit).map( |s|
if let Ok(n) = s.parse::<u64>() {
Int(n)
} else {
BadInt(s.into())
}
),
c => Unrecognized(c)
}
)
}
fn main() {
let code = r#"
if foo > bar {
foo = 1
}
"#;
for (line_num, col_range, token) in tokens_in(code.lines(), &tokenizer) {
println!("On line {line_num} at columns {col_range:?}: {token:?}");
}
}