use crate::SyntaxKind;
use super::char_len_utf8;
pub fn is_ident_char(bytes: &[u8], pos: usize) -> bool {
let b = bytes[pos];
if b.is_ascii_alphabetic() || b == b'_' {
return true;
}
if b >= 0x80 {
let ch = decode_char_at(bytes, pos);
return is_ink_ident_codepoint(ch);
}
false
}
fn decode_char_at(bytes: &[u8], pos: usize) -> char {
let len = char_len_utf8(bytes, pos);
let slice = &bytes[pos..pos + len];
let s = std::str::from_utf8(slice).unwrap_or("\u{FFFD}");
s.chars().next().unwrap_or('\u{FFFD}')
}
pub fn is_ink_ident_codepoint(ch: char) -> bool {
let c = ch as u32;
match c {
0x0080..=0x024F
| 0x0590..=0x06FF
| 0x3041..=0x3096
| 0x30A0..=0x30FC
| 0x4E00..=0x9FFF
| 0xAC00..=0xD7AF => true,
0x0370..=0x03FF => !matches!(
c,
0x0374 | 0x0375 | 0x0378..=0x0385 | 0x0387 | 0x038B | 0x038D | 0x03A2
),
0x0400..=0x04FF => !matches!(c, 0x0482..=0x0489),
0x0530..=0x058F => !matches!(c, 0x0530 | 0x0557..=0x0560 | 0x0588..=0x058E),
_ => false,
}
}
pub fn scan_ident(bytes: &[u8], mut pos: usize) -> usize {
while pos < bytes.len() {
let b = bytes[pos];
if b.is_ascii_alphanumeric() || b == b'_' {
pos += 1;
} else if b >= 0x80 {
let ch = decode_char_at(bytes, pos);
if is_ink_ident_codepoint(ch) {
pos += char_len_utf8(bytes, pos);
} else {
break;
}
} else {
break;
}
}
pos
}
pub fn classify_keyword(text: &str) -> SyntaxKind {
use SyntaxKind::{
IDENT, KW_AND, KW_CONST, KW_CYCLE, KW_DONE, KW_ELSE, KW_END, KW_EXTERNAL, KW_FALSE,
KW_FUNCTION, KW_HAS, KW_HASNT, KW_INCLUDE, KW_LIST, KW_MOD, KW_NOT, KW_ONCE, KW_OR, KW_REF,
KW_RETURN, KW_SHUFFLE, KW_STOPPING, KW_TEMP, KW_TODO, KW_TRUE, KW_VAR,
};
match text {
"INCLUDE" => KW_INCLUDE,
"EXTERNAL" => KW_EXTERNAL,
"VAR" => KW_VAR,
"CONST" => KW_CONST,
"LIST" => KW_LIST,
"temp" => KW_TEMP,
"return" => KW_RETURN,
"ref" => KW_REF,
"true" => KW_TRUE,
"false" => KW_FALSE,
"not" => KW_NOT,
"and" => KW_AND,
"or" => KW_OR,
"mod" => KW_MOD,
"has" => KW_HAS,
"hasnt" => KW_HASNT,
"else" => KW_ELSE,
"function" => KW_FUNCTION,
"stopping" => KW_STOPPING,
"cycle" => KW_CYCLE,
"shuffle" => KW_SHUFFLE,
"once" => KW_ONCE,
"DONE" => KW_DONE,
"END" => KW_END,
"TODO" => KW_TODO,
_ => IDENT,
}
}