use text_scanner::{ext::JsonCScannerExt, Scanner};
use crate::{impl_lexer_from_scanner, JsonToken, ScanToken, ScannerExt, TokenSpan};
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum JsonCToken {
Space,
LineComment,
BlockComment,
String,
Number,
Null,
True,
False,
Punct,
Delim,
Unknown,
}
impl ScanToken for JsonCToken {
fn scan_token<'text>(scanner: &mut Scanner<'text>) -> Option<(Self, TokenSpan<'text>)> {
if let Ok((r, _s)) = scanner.scan_jsonc_line_comment() {
return Some((Self::LineComment, scanner.span(r)));
} else if let Ok((r, _s)) = scanner.scan_jsonc_block_comment() {
return Some((Self::BlockComment, scanner.span(r)));
}
let (tok, span) = JsonToken::scan_token(scanner)?;
match tok {
JsonToken::Space => Some((JsonCToken::Space, span)),
JsonToken::String => Some((JsonCToken::String, span)),
JsonToken::Number => Some((JsonCToken::Number, span)),
JsonToken::Null => Some((JsonCToken::Null, span)),
JsonToken::True => Some((JsonCToken::True, span)),
JsonToken::False => Some((JsonCToken::False, span)),
JsonToken::Punct => Some((JsonCToken::Punct, span)),
JsonToken::Delim => Some((JsonCToken::Delim, span)),
JsonToken::Unknown => Some((JsonCToken::Unknown, span)),
}
}
}
#[derive(Clone, Debug)]
pub struct JsonCLexer<'text> {
scanner: Scanner<'text>,
}
impl<'text> JsonCLexer<'text> {
#[inline]
pub fn new(text: &'text str) -> Self {
Self {
scanner: Scanner::new(text),
}
}
}
impl_lexer_from_scanner!('text, JsonCLexer<'text>, JsonCToken, scanner);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_jsonc_lexer_spans() {
let input = include_str!("../../../text-scanner/src/ext/rust.rs");
let mut output = String::new();
let lexer = JsonCLexer::new(input);
for (_tok, span) in lexer {
output.push_str(span.as_str());
}
assert_eq!(input, output);
}
}