2021-07-24 20:10:10 -04:00
|
|
|
use std::{borrow::Cow, iter::Peekable, str::Chars, sync::Arc};
|
2020-04-12 19:37:12 -04:00
|
|
|
|
|
|
|
use codemap::File;
|
2020-01-04 22:55:04 -05:00
|
|
|
|
2020-03-29 13:28:17 -04:00
|
|
|
use crate::Token;
|
2020-01-26 16:50:08 -05:00
|
|
|
|
2020-05-23 01:17:14 -04:00
|
|
|
const FORM_FEED: char = '\x0C';
|
2020-02-28 18:27:32 -05:00
|
|
|
|
2020-01-04 22:55:04 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2021-07-24 20:10:10 -04:00
|
|
|
pub(crate) struct Lexer<'a> {
|
|
|
|
buf: Cow<'a, [Token]>,
|
2021-07-11 15:12:46 -04:00
|
|
|
cursor: usize,
|
|
|
|
amt_peeked: usize,
|
|
|
|
}
|
|
|
|
|
2021-07-24 20:10:10 -04:00
|
|
|
impl<'a> Lexer<'a> {
|
2021-07-11 15:12:46 -04:00
|
|
|
fn peek_cursor(&self) -> usize {
|
|
|
|
self.cursor + self.amt_peeked
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peek(&self) -> Option<Token> {
|
|
|
|
self.buf.get(self.peek_cursor()).copied()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn reset_cursor(&mut self) {
|
|
|
|
self.amt_peeked = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peek_next(&mut self) -> Option<Token> {
|
|
|
|
self.amt_peeked += 1;
|
|
|
|
|
|
|
|
self.peek()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peek_previous(&mut self) -> Option<Token> {
|
2021-07-12 01:59:30 -04:00
|
|
|
self.buf.get(self.peek_cursor().checked_sub(1)?).copied()
|
2021-07-11 15:12:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn peek_forward(&mut self, n: usize) -> Option<Token> {
|
|
|
|
self.amt_peeked += n;
|
|
|
|
|
|
|
|
self.peek()
|
|
|
|
}
|
|
|
|
|
2021-07-12 01:59:30 -04:00
|
|
|
/// Peeks `n` from current peeked position without modifying cursor
|
|
|
|
pub fn peek_n(&self, n: usize) -> Option<Token> {
|
|
|
|
self.buf.get(self.peek_cursor() + n).copied()
|
|
|
|
}
|
|
|
|
|
2021-07-11 15:12:46 -04:00
|
|
|
pub fn peek_backward(&mut self, n: usize) -> Option<Token> {
|
|
|
|
self.amt_peeked = self.amt_peeked.checked_sub(n)?;
|
|
|
|
|
|
|
|
self.peek()
|
|
|
|
}
|
|
|
|
|
2021-07-12 01:59:30 -04:00
|
|
|
/// Set cursor to position and reset peek
|
|
|
|
pub fn set_cursor(&mut self, cursor: usize) {
|
|
|
|
self.cursor = cursor;
|
|
|
|
self.amt_peeked = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn cursor(&self) -> usize {
|
|
|
|
self.cursor
|
|
|
|
}
|
2021-07-11 15:12:46 -04:00
|
|
|
}
|
|
|
|
|
2021-07-24 20:10:10 -04:00
|
|
|
impl<'a> Iterator for Lexer<'a> {
|
2021-07-11 15:12:46 -04:00
|
|
|
type Item = Token;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
self.buf.get(self.cursor).copied().map(|tok| {
|
|
|
|
self.cursor += 1;
|
|
|
|
self.amt_peeked = self.amt_peeked.saturating_sub(1);
|
|
|
|
tok
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct TokenLexer<'a> {
|
2020-01-04 22:55:04 -05:00
|
|
|
buf: Peekable<Chars<'a>>,
|
2021-07-11 15:12:46 -04:00
|
|
|
cursor: usize,
|
|
|
|
file: Arc<File>,
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
|
2021-07-11 15:12:46 -04:00
|
|
|
impl<'a> Iterator for TokenLexer<'a> {
|
2020-01-04 22:55:04 -05:00
|
|
|
type Item = Token;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
2020-03-29 13:28:17 -04:00
|
|
|
let kind = match self.buf.next()? {
|
2020-05-01 19:16:57 -04:00
|
|
|
FORM_FEED => '\n',
|
2020-01-07 18:37:28 -05:00
|
|
|
'\r' => {
|
2020-03-29 13:28:17 -04:00
|
|
|
if self.buf.peek() == Some(&'\n') {
|
2021-07-11 15:12:46 -04:00
|
|
|
self.cursor += 1;
|
2020-03-29 13:28:17 -04:00
|
|
|
self.buf.next();
|
|
|
|
}
|
2020-05-01 19:16:57 -04:00
|
|
|
'\n'
|
2020-01-07 18:37:28 -05:00
|
|
|
}
|
2020-03-29 13:28:17 -04:00
|
|
|
c => c,
|
2020-01-04 22:55:04 -05:00
|
|
|
};
|
2020-04-12 19:37:12 -04:00
|
|
|
let len = kind.len_utf8();
|
|
|
|
let pos = self
|
|
|
|
.file
|
|
|
|
.span
|
2021-07-11 15:12:46 -04:00
|
|
|
.subspan(self.cursor as u64, (self.cursor + len) as u64);
|
|
|
|
self.cursor += len;
|
2021-07-03 19:15:31 -04:00
|
|
|
Some(Token { pos, kind })
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-24 20:10:10 -04:00
|
|
|
impl<'a> Lexer<'a> {
|
2021-07-11 15:12:46 -04:00
|
|
|
pub fn new_from_file(file: &Arc<File>) -> Self {
|
|
|
|
let buf = TokenLexer {
|
|
|
|
file: Arc::clone(file),
|
2020-08-10 06:53:00 -04:00
|
|
|
buf: file.source().chars().peekable(),
|
2021-07-11 15:12:46 -04:00
|
|
|
cursor: 0,
|
|
|
|
}
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
Self::new(buf)
|
|
|
|
}
|
|
|
|
|
2021-07-24 20:10:10 -04:00
|
|
|
pub fn new(buf: Vec<Token>) -> Self {
|
2021-07-11 15:12:46 -04:00
|
|
|
Lexer {
|
2021-07-24 20:10:10 -04:00
|
|
|
buf: Cow::Owned(buf),
|
|
|
|
cursor: 0,
|
|
|
|
amt_peeked: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_ref(buf: &'a [Token]) -> Lexer<'a> {
|
|
|
|
Lexer {
|
|
|
|
buf: Cow::Borrowed(buf),
|
2021-07-11 15:12:46 -04:00
|
|
|
cursor: 0,
|
|
|
|
amt_peeked: 0,
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|