Add token reader and access to last token in checker function
Signed-off-by: trivernis <trivernis@protonmail.com>master
parent
652045becb
commit
8cb21fcaca
@ -1,3 +1,4 @@
|
|||||||
mod test_input;
|
mod test_input;
|
||||||
mod test_lexer;
|
mod test_lexer;
|
||||||
mod test_token;
|
mod test_token;
|
||||||
|
mod test_token_reader;
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
use crate::token::{EOFToken, Token};
|
||||||
|
use crate::token_reader::TokenReader;
|
||||||
|
|
||||||
|
struct AToken;
|
||||||
|
struct BToken;
|
||||||
|
struct CToken;
|
||||||
|
|
||||||
|
fn get_reader() -> TokenReader {
|
||||||
|
let tokens = vec![
|
||||||
|
Token::new(AToken),
|
||||||
|
Token::new(BToken),
|
||||||
|
Token::new(AToken),
|
||||||
|
Token::new(CToken),
|
||||||
|
Token::new(CToken),
|
||||||
|
Token::new(EOFToken),
|
||||||
|
];
|
||||||
|
|
||||||
|
TokenReader::new(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn peek_does_not_consume() {
|
||||||
|
let reader = get_reader();
|
||||||
|
|
||||||
|
assert!(reader.peek_is::<AToken>());
|
||||||
|
assert!(!reader.peek_is::<BToken>());
|
||||||
|
assert!(reader.peek_is::<AToken>());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn consume_does_consume() {
|
||||||
|
let mut reader = get_reader();
|
||||||
|
assert!(reader.consume_as::<AToken>().is_some());
|
||||||
|
assert!(reader.consume_as::<BToken>().is_some());
|
||||||
|
assert!(reader.consume_as::<AToken>().is_some());
|
||||||
|
assert!(reader.consume_as::<CToken>().is_some());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_eof_works() {
|
||||||
|
let mut reader = get_reader();
|
||||||
|
reader.seek(4);
|
||||||
|
assert!(!reader.check_eof());
|
||||||
|
reader.seek(5);
|
||||||
|
assert!(reader.check_eof());
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn peek_and_consume_returns_eof_on_input_end() {
|
||||||
|
let mut reader = get_reader();
|
||||||
|
reader.seek(4);
|
||||||
|
assert!(reader.consume_as::<EOFToken>().is_none());
|
||||||
|
assert!(reader.consume_as::<EOFToken>().is_some());
|
||||||
|
assert!(reader.consume_as::<EOFToken>().is_some());
|
||||||
|
assert!(reader.consume_as::<EOFToken>().is_some());
|
||||||
|
reader.seek(0);
|
||||||
|
assert!(reader.consume_as::<EOFToken>().is_none());
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
use crate::token::{EOFToken, Token};
|
||||||
|
|
||||||
|
pub struct TokenReader {
|
||||||
|
tokens: Vec<Token>,
|
||||||
|
index: usize,
|
||||||
|
eof: Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TokenReader {
|
||||||
|
/// Creates a new token reader
|
||||||
|
pub fn new(mut tokens: Vec<Token>) -> Self {
|
||||||
|
if tokens.last().is_none() || !tokens.last().unwrap().is::<EOFToken>() {
|
||||||
|
// ensure that the last token always is an EOF Token
|
||||||
|
tokens.push(Token::new(EOFToken));
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
tokens,
|
||||||
|
index: 0,
|
||||||
|
eof: Token::new(EOFToken),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peeks the next token
|
||||||
|
#[inline]
|
||||||
|
pub fn peek(&self) -> &Token {
|
||||||
|
self.tokens.get(self.index).unwrap_or(&self.eof)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the next token is of a specific type without consuming it
|
||||||
|
#[inline]
|
||||||
|
pub fn peek_is<T: 'static>(&self) -> bool {
|
||||||
|
self.peek().is::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Peeks the next token and tries to return is as a concrete type
|
||||||
|
#[inline]
|
||||||
|
pub fn peek_as<T: 'static>(&self) -> Option<&T> {
|
||||||
|
self.peek().try_as::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the next token and returns it
|
||||||
|
pub fn consume(&mut self) -> &Token {
|
||||||
|
self.index += 1;
|
||||||
|
self.tokens.get(self.index - 1).unwrap_or(&self.eof)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the next token and tries to return it as the specified type
|
||||||
|
#[inline]
|
||||||
|
pub fn consume_as<T: 'static>(&mut self) -> Option<&T> {
|
||||||
|
self.consume().try_as::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Seeks to the given index
|
||||||
|
#[inline]
|
||||||
|
pub fn seek(&mut self, to_index: usize) {
|
||||||
|
self.index = to_index
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns if EOF has been reached
|
||||||
|
#[inline]
|
||||||
|
pub fn check_eof(&self) -> bool {
|
||||||
|
self.peek_is::<EOFToken>()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue