use super::errors::LexResult;
use super::*;
impl Lexer {
pub(super) fn lex_jsdoc(&mut self) -> SyntaxKind {
let remaining = self.remaining();
if remaining.starts_with("*/") {
self.advance(2);
self.pop_mode();
return SyntaxKind::JsDocClose;
}
let text_start = self.pos;
while self.pos < self.input.len() {
let r = self.remaining();
if r.starts_with("*/") {
break;
}
if let Some(c) = self.peek() {
self.advance(c.len_utf8());
}
}
if self.pos > text_start {
SyntaxKind::Text
} else {
SyntaxKind::Text
}
}
pub(super) fn lex_string_literal(&mut self) -> LexResult<SyntaxKind> {
let start_pos = self.pos;
let remaining = self.remaining();
if remaining.starts_with("\"") {
self.advance(1);
self.pop_mode();
return Ok(SyntaxKind::DoubleQuote);
}
if remaining.starts_with("@{") {
self.advance(2);
self.push_mode(LexerMode::Interpolation);
self.brace_depth = 1;
return Ok(SyntaxKind::At);
}
if remaining.starts_with("\\") && remaining.len() >= 2 {
self.advance(2);
return Ok(SyntaxKind::Text);
}
if remaining.starts_with("\\") && remaining.len() < 2 {
let sequence = remaining
.chars()
.nth(1)
.map_or(String::new(), |c| c.to_string());
return Err(LexError::invalid_escape(self.pos, &sequence));
}
let text_start = self.pos;
while self.pos < self.input.len() {
let r = self.remaining();
if r.starts_with("\"") || r.starts_with("@{") || r.starts_with("\\") {
break;
}
if let Some(c) = self.peek() {
self.advance(c.len_utf8());
}
}
if self.pos > text_start {
Ok(SyntaxKind::Text)
} else if self.pos >= self.input.len() {
Err(LexError::unterminated_string(self.pos, start_pos, '"'))
} else {
Err(LexError::unterminated_string(self.pos, start_pos, '"'))
}
}
pub(super) fn lex_template_literal(&mut self) -> LexResult<SyntaxKind> {
let start_pos = self.pos;
let remaining = self.remaining();
if remaining.starts_with("`") {
self.advance(1);
self.pop_mode();
return Ok(SyntaxKind::Backtick);
}
if remaining.starts_with("${") {
self.advance(2);
self.push_mode(LexerMode::TemplateExpr);
self.brace_depth = 1;
return Ok(SyntaxKind::DollarBrace);
}
if remaining.starts_with("@{") {
self.advance(2);
self.push_mode(LexerMode::Interpolation);
self.brace_depth = 1;
return Ok(SyntaxKind::At);
}
if remaining.starts_with("\\") && remaining.len() >= 2 {
self.advance(2);
return Ok(SyntaxKind::Text);
}
if remaining.starts_with("\\") && remaining.len() < 2 {
let sequence = remaining
.chars()
.nth(1)
.map_or(String::new(), |c| c.to_string());
return Err(LexError::invalid_escape(self.pos, &sequence));
}
let text_start = self.pos;
while self.pos < self.input.len() {
let r = self.remaining();
if r.starts_with("`")
|| r.starts_with("${")
|| r.starts_with("@{")
|| r.starts_with("\\")
{
break;
}
if let Some(c) = self.peek() {
self.advance(c.len_utf8());
}
}
if self.pos > text_start {
Ok(SyntaxKind::Text)
} else if self.pos >= self.input.len() {
Err(LexError::unterminated_template(self.pos, start_pos))
} else {
Err(LexError::unterminated_template(self.pos, start_pos))
}
}
}