draconic/src/reader.rs
Jason Travis Smith 5103ed2971 The Draconian compiler can now read a file.
A file can be read and placed into a Reader buffer for lexicographical
analysis. This buffer can be consumed on a character by character basis.
2016-07-16 17:07:47 -04:00

162 lines
3.4 KiB
Rust

use std::fs::File;
use std::io::Read;
use std::path::Path;
// TODO: Make this work on only a predetermined size of a buffer.
/// Stores some input and allows it to be
/// read on a character by character basis.
///
pub struct Reader
{
/// The current position in the buffer.
position: usize,
/// The buffer of the input data to be read.
buffer: Vec<char>
}
impl Reader
{
/// Create a new empty Reader.
pub fn new() -> Reader
{
Reader
{
position: 0usize,
buffer: Vec::new(),
}
}
/// Create a new reader from a File.
pub fn from_file<F>(filepath: F) -> Reader
where F: AsRef<Path>
{
let mut reader: Reader;
// Create a new Reader and load the data
// for it from the file at the given filepath.
reader = Reader::new();
reader.load_from_file(filepath);
reader
}
/// Create a new reader from a String.
pub fn from_string(data: String) -> Reader
{
let mut reader: Reader;
// Create a new Reader and load the data to it.
reader = Reader::new();
reader.load_from_string(data);
reader
}
/// Reset the Reader back to the starting position.
pub fn reset(&mut self)
{
// Move back to the start of the buffer.
self.position = 0usize;
}
/// Clear the Reader of all data.
pub fn clear(&mut self)
{
self.buffer = Vec::new();
self.reset();
}
/// Clears the Reader and sets it to read from a File.
pub fn load_from_file<F>(&mut self, filepath: F)
where F: AsRef<Path>
{
let mut data: String;
// Open the file for reading and load the
// data into a String that will be parsed.
data = String::new();
match File::open(filepath.as_ref())
{
Ok(mut file) =>
{
match file.read_to_string(&mut data)
{
Ok(bytes_read) =>
{
info!("{} bytes read from {:?}",
bytes_read, filepath.as_ref());
}
Err(error) =>
{
error!("{}", error);
}
}
}
Err(error) =>
{
error!("{}", error);
}
}
// Load the String read from the file.
self.load_from_string(data);
}
/// Clears the Reader and sets it to read from the given data.
pub fn load_from_string(&mut self, data: String)
{
// Clear the Reader.
self.clear();
// Parse the String that the reader is
// reading from as a set of characters
// in the Reader's buffer.
for character in data.chars()
{
self.buffer.push(character);
}
}
/// Get the current character.
pub fn get_char(&self) -> Result<char, &'static str>
{
if self.is_eof() == false
{
Ok(self.buffer[self.position])
}
else
{
Err("Unable to read character. \
No characters left in the input buffer.")
}
}
/// Get the current character and move the
/// Reader on to the next character.
pub fn consume_char(&mut self) -> Result<char, &'static str>
{
let character: char;
character = try!(self.get_char());
self.position += 1;
Ok(character)
}
///
fn is_eof(&self) -> bool
{
self.position >= self.buffer.len()
}
}