|
|
@ -161,7 +161,7 @@ impl<R> Lexer<R> { |
|
|
|
)) |
|
|
|
)) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
InputElement::RegExp => { |
|
|
|
InputElement::RegExp | InputElement::HashbangOrRegExp => { |
|
|
|
// Can be a regular expression.
|
|
|
|
// Can be a regular expression.
|
|
|
|
RegexLiteral.lex(&mut self.cursor, start, interner) |
|
|
|
RegexLiteral.lex(&mut self.cursor, start, interner) |
|
|
|
} |
|
|
|
} |
|
|
@ -214,28 +214,34 @@ impl<R> Lexer<R> { |
|
|
|
{ |
|
|
|
{ |
|
|
|
let _timer = Profiler::global().start_event("next()", "Lexing"); |
|
|
|
let _timer = Profiler::global().start_event("next()", "Lexing"); |
|
|
|
|
|
|
|
|
|
|
|
let (start, next_ch) = loop { |
|
|
|
let mut start = self.cursor.pos(); |
|
|
|
let start = self.cursor.pos(); |
|
|
|
let Some(mut next_ch) = self.cursor.next_char()? else { |
|
|
|
if let Some(next_ch) = self.cursor.next_char()? { |
|
|
|
return Ok(None); |
|
|
|
// Ignore whitespace
|
|
|
|
|
|
|
|
if !is_whitespace(next_ch) { |
|
|
|
|
|
|
|
break (start, next_ch); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return Ok(None); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
//handle hashbang here so the below match block still throws error on
|
|
|
|
// If the goal symbol is HashbangOrRegExp, then we need to check if the next token is a hashbang comment.
|
|
|
|
//# if position isn't (1, 1)
|
|
|
|
// Since the goal symbol is only valid for the first token, we need to change it to RegExp after the first token.
|
|
|
|
if start.column_number() == 1 |
|
|
|
if self.get_goal() == InputElement::HashbangOrRegExp { |
|
|
|
&& start.line_number() == 1 |
|
|
|
self.set_goal(InputElement::RegExp); |
|
|
|
&& next_ch == 0x23 |
|
|
|
if next_ch == 0x23 && self.cursor.peek_char()? == Some(0x21) { |
|
|
|
&& self.cursor.peek_char()? == Some(0x21) |
|
|
|
let _token = HashbangComment.lex(&mut self.cursor, start, interner); |
|
|
|
{ |
|
|
|
return self.next(interner); |
|
|
|
let _token = HashbangComment.lex(&mut self.cursor, start, interner); |
|
|
|
}; |
|
|
|
return self.next(interner); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Ignore whitespace
|
|
|
|
|
|
|
|
if is_whitespace(next_ch) { |
|
|
|
|
|
|
|
loop { |
|
|
|
|
|
|
|
start = self.cursor.pos(); |
|
|
|
|
|
|
|
let Some(next) = self.cursor.next_char()? else { |
|
|
|
|
|
|
|
return Ok(None); |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
if !is_whitespace(next) { |
|
|
|
|
|
|
|
next_ch = next; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if let Ok(c) = char::try_from(next_ch) { |
|
|
|
if let Ok(c) = char::try_from(next_ch) { |
|
|
|
let token = match c { |
|
|
|
let token = match c { |
|
|
@ -392,6 +398,7 @@ pub(crate) enum InputElement { |
|
|
|
Div, |
|
|
|
Div, |
|
|
|
RegExp, |
|
|
|
RegExp, |
|
|
|
TemplateTail, |
|
|
|
TemplateTail, |
|
|
|
|
|
|
|
HashbangOrRegExp, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl Default for InputElement { |
|
|
|
impl Default for InputElement { |
|
|
|