use swc_common::input::Input;
use crate::{byte_search, lexer::search::SafeByteMatchTable, safe_byte_match_table, Lexer};
const B_VT: u8 = 0x0b;
const B_FF: u8 = 0x0c;
#[inline]
pub fn is_irregular_whitespace(c: char) -> bool {
const ZWNBSP: char = '\u{feff}';
const VT: char = '\u{b}';
const FF: char = '\u{c}';
const NBSP: char = '\u{a0}';
const NEL: char = '\u{85}';
const OGHAM_SPACE_MARK: char = '\u{1680}';
const EN_QUAD: char = '\u{2000}';
const ZWSP: char = '\u{200b}';
const NNBSP: char = '\u{202f}';
const MMSP: char = '\u{205f}';
const IDEOGRAPHIC_SPACE: char = '\u{3000}';
matches!(
c,
VT | FF | NBSP | ZWNBSP | NEL | OGHAM_SPACE_MARK | EN_QUAD
..=ZWSP | NNBSP | MMSP | IDEOGRAPHIC_SPACE
)
}
#[inline]
pub fn is_irregular_line_terminator(c: char) -> bool {
const LS: char = '\u{2028}';
const PS: char = '\u{2029}';
matches!(c, LS | PS)
}
type ByteHandler = fn(&mut Lexer<'_>) -> bool;
#[rustfmt::skip]
static BYTE_HANDLERS: [ByteHandler; 256] = [
___, ___, ___, ___, ___, ___, ___, ___, ___, SPC, NLN, SPC, SPC, NLN, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, SPC, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, SLH, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, UNI, ];
const ___: ByteHandler = |_| false;
const NLN: ByteHandler = |lexer| {
static NOT_REGULAR_WHITESPACE_OR_LINE_BREAK_TABLE: SafeByteMatchTable =
safe_byte_match_table!(|b| !matches!(b, b' ' | b'\t' | B_VT | B_FF | b'\r' | b'\n'));
lexer.state.had_line_break = true;
byte_search! {
lexer: lexer,
table: NOT_REGULAR_WHITESPACE_OR_LINE_BREAK_TABLE,
handle_eof: return false,
};
true
};
const SPC: ByteHandler = |lexer| {
static NOT_SPC: SafeByteMatchTable =
safe_byte_match_table!(|b| !matches!(b, b' ' | b'\t' | B_VT | B_FF));
byte_search! {
lexer: lexer,
table: NOT_SPC,
handle_eof: return false,
};
true
};
const SLH: ByteHandler = |lexer| match lexer.peek() {
Some(b'/') => {
lexer.skip_line_comment(2);
true
}
Some(b'*') => {
lexer.skip_block_comment();
true
}
_ => false,
};
const UNI: ByteHandler = |lexer| {
let Some(c) = lexer.cur_as_char() else {
return false;
};
if is_irregular_whitespace(c) {
lexer.bump(c.len_utf8());
true
} else if is_irregular_line_terminator(c) {
lexer.bump(c.len_utf8());
lexer.state.had_line_break = true;
true
} else {
false
}
};
impl<'a> Lexer<'a> {
#[inline]
pub fn skip_space(&mut self) {
loop {
let byte = match self.input.cur() {
Some(v) => v,
None => return,
};
if byte.wrapping_sub(b'!') < 0x5f && byte != b'/' {
break;
}
let handler = unsafe { *(&BYTE_HANDLERS as *const ByteHandler).offset(byte as isize) };
if !handler(self) {
break;
}
}
}
}