use crate::syntax::{Language, Syntax};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum TokenKind {
Whitespace,
Newline,
Indent,
LineComment,
BlockComment,
String,
Interpolation,
Number,
Identifier,
Regex,
Punctuation,
Unterminated,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Token {
pub kind: TokenKind,
pub start: usize,
pub end: usize,
pub line: u32,
pub column: u32,
}
impl Token {
#[must_use]
pub fn text<'source>(&self, source: &'source str) -> &'source str {
source.get(self.start..self.end).unwrap_or_default()
}
#[must_use]
pub const fn is_trivia(&self) -> bool {
matches!(
self.kind,
TokenKind::Whitespace
| TokenKind::Newline
| TokenKind::Indent
| TokenKind::LineComment
| TokenKind::BlockComment
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Mode {
#[default]
Lossless,
Lite,
}
#[must_use]
pub fn tokenize(source: &str, language: Language) -> Vec<Token> {
Tokenizer::new(source, language).collect()
}
#[must_use]
pub fn tokenize_lite(source: &str, language: Language) -> Vec<Token> {
Tokenizer::new(source, language).mode(Mode::Lite).collect()
}
pub struct Tokenizer<'source> {
source: &'source str,
syntax: Syntax,
mode: Mode,
bytes: &'source [u8],
offset: usize,
line: u32,
column: u32,
value_before: bool,
at_line_start: bool,
}
mod construction;
mod lexemes;
mod scanner;
mod strings;
#[cfg(test)]
mod tests;