#![allow(dead_code)]
use alkale::{span::Spanned, token::Token, FinalizedLexerResult, LexerResult, SourceCodeScanner};
#[derive(Debug, Clone)]
enum ForeachToken<'a> {
Identifier(&'a str),
OpenBracket, CloseBracket, OpenBrace, CloseBrace, Semicolon, Assign, ConstAssign, Foreach, Return, }
fn tokenize(source: &str) -> FinalizedLexerResult<ForeachToken<'_>> {
use ForeachToken::{
Assign, CloseBrace, CloseBracket, ConstAssign, Foreach, Identifier, OpenBrace, OpenBracket,
Return, Semicolon,
};
let context = SourceCodeScanner::new(source);
let mut result = LexerResult::new();
while context.has_next() {
let Spanned {
span,
data: identifier,
} = context.capture_str(|| {
while let Some(c) = context.peek() {
if is_identifier_char(c) {
context.skip();
} else {
break;
}
}
});
if span.is_empty() {
let Spanned { span, data } = context.next_span().unwrap();
let token = match data {
'[' => OpenBracket,
']' => CloseBracket,
'{' => OpenBrace,
'}' => CloseBrace,
';' => Semicolon,
_ => continue, };
result.push_token(Token::new(token, span));
continue;
};
if identifier.starts_with("//") {
context.skip_until('\n');
continue;
}
let token = match identifier {
"=" => Assign,
":=" => ConstAssign,
"=>" => Foreach,
"->" => Return,
_ => Identifier(identifier),
};
result.push_token(Token::new(token, span));
}
result.finalize()
}
fn is_identifier_char(x: char) -> bool {
!x.is_whitespace() && x != ';' && x != '[' && x != ']' && x != '{' && x != '}'
}
fn main() {
let program = r#"
false := [];
true := [[]];
// True -> False, False -> True
! inp {
v := inp => -> false;
-> true;
}
// True if input array contains only truthy values.
&& inp {
v := inp => _ := ! v => -> false;
-> true;
}
// True if input array contains at least 1 truthy value.
|| inp v := inp => _ := v => -> true;
// True if number of truthy values in input array is odd
^ inp {
out = false;
v := inp => _ := v => out = ! out;
-> out;
}
"#;
let result = tokenize(program);
println!("{result:#?}");
}