2020-01-04 22:55:04 -05:00
|
|
|
use std::iter::Peekable;
|
|
|
|
use std::str::Chars;
|
2020-04-12 19:37:12 -04:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
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-03-29 13:28:17 -04:00
|
|
|
pub const FORM_FEED: char = '\x0C';
|
2020-02-28 18:27:32 -05:00
|
|
|
|
2020-01-04 22:55:04 -05:00
|
|
|
#[derive(Debug, Clone)]
|
2020-01-20 13:15:47 -05:00
|
|
|
pub(crate) struct Lexer<'a> {
|
2020-01-04 22:55:04 -05:00
|
|
|
buf: Peekable<Chars<'a>>,
|
2020-04-12 19:37:12 -04:00
|
|
|
pos: usize,
|
|
|
|
file: &'a Arc<File>,
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Iterator for Lexer<'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-04-12 19:37:12 -04:00
|
|
|
'\n' | 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') {
|
2020-04-12 19:37:12 -04:00
|
|
|
self.pos += 1;
|
2020-03-29 13:28:17 -04:00
|
|
|
self.buf.next();
|
|
|
|
'\n'
|
|
|
|
} else {
|
|
|
|
'\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
|
|
|
|
.subspan(self.pos as u64, (self.pos + len) as u64);
|
|
|
|
self.pos += len;
|
|
|
|
Some(Token { kind, pos })
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Lexer<'a> {
|
2020-04-12 19:37:12 -04:00
|
|
|
pub fn new(file: &'a Arc<File>) -> Lexer<'a> {
|
2020-01-04 22:55:04 -05:00
|
|
|
Lexer {
|
2020-04-21 18:22:26 -04:00
|
|
|
buf: file.source().chars().peekable(),
|
2020-04-12 19:37:12 -04:00
|
|
|
pos: 0,
|
|
|
|
file,
|
2020-01-04 22:55:04 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|