use harper_core::Lrc;
use harper_core::Span;
use harper_core::Token;
use harper_core::parsers::{Markdown, MarkdownOptions, Parser};
use super::without_initiators;
#[derive(Clone)]
pub struct Lua {
inner: Lrc<dyn Parser>,
}
impl Lua {
pub fn new(parser: Lrc<dyn Parser>) -> Self {
Self { inner: parser }
}
pub fn new_markdown(markdown_options: MarkdownOptions) -> Self {
Self::new(Lrc::new(Markdown::new(markdown_options)))
}
}
impl Parser for Lua {
fn parse(&self, source: &[char]) -> Vec<Token> {
let mut tokens = Vec::new();
let mut chars_traversed = 0;
for line in source.split(|c| *c == '\n') {
if starts_with_prefix(line) {
tokens.push(Token::new(
Span::empty(chars_traversed),
harper_core::TokenKind::Newline(2),
));
chars_traversed += line.len() + 1;
continue;
}
let mut new_tokens = parse_line(line, self.inner.clone());
if chars_traversed + line.len() < source.len() {
new_tokens.push(Token::new(
Span::new_with_len(line.len(), 1),
harper_core::TokenKind::Newline(1),
));
}
new_tokens
.iter_mut()
.for_each(|t| t.span.push_by(chars_traversed));
chars_traversed += line.len() + 1;
tokens.append(&mut new_tokens);
}
tokens
}
}
fn starts_with_prefix(source: &[char]) -> bool {
let actual = without_initiators(source);
let actual_chars = actual.get_content(source);
matches!(actual_chars, ['@', ..])
}
fn parse_line(source: &[char], parser: Lrc<dyn Parser>) -> Vec<Token> {
let actual = without_initiators(source);
if actual.is_empty() {
return Vec::new();
}
let source = actual.get_content(source);
let mut new_tokens = parser.parse(source);
new_tokens
.iter_mut()
.for_each(|t| t.span.push_by(actual.start));
new_tokens
}