grass/src/lexer.rs

137 lines
3.0 KiB
Rust
Raw Normal View History

use std::{borrow::Cow, iter::Peekable, str::Chars, sync::Arc};
2020-04-12 19:37:12 -04:00
use codemap::File;
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
#[derive(Debug, Clone)]
pub(crate) struct Lexer<'a> {
buf: Cow<'a, [Token]>,
2021-07-11 15:12:46 -04:00
cursor: usize,
amt_peeked: usize,
}
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
}
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> {
buf: Peekable<Chars<'a>>,
2021-07-11 15:12:46 -04:00
cursor: usize,
file: Arc<File>,
}
2021-07-11 15:12:46 -04:00
impl<'a> Iterator for TokenLexer<'a> {
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',
'\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-03-29 13:28:17 -04:00
c => c,
};
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 })
}
}
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)
}
pub fn new(buf: Vec<Token>) -> Self {
2021-07-11 15:12:46 -04:00
Lexer {
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,
}
}
}