|
|
@ -1,9 +1,9 @@
|
|
|
|
use crate::error::LexError;
|
|
|
|
use crate::error::LexError;
|
|
|
|
use std::{collections::VecDeque, fmt, ops::Range, str::Chars};
|
|
|
|
use std::{collections::VecDeque, fmt, ops::Range, str::Chars};
|
|
|
|
|
|
|
|
|
|
|
|
/// The position of a specific glyph within a corpus of text. We use this for rendering error
|
|
|
|
/// A position a some two dimensional space defined by lines and columns, specifically concerned
|
|
|
|
/// messages and communicating to the user the location of errors.
|
|
|
|
/// with positions of characters within text
|
|
|
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
|
|
|
#[derive(PartialEq, Clone, Copy)]
|
|
|
|
pub struct Position {
|
|
|
|
pub struct Position {
|
|
|
|
/// The visual line in which this glyph appears in the source text
|
|
|
|
/// The visual line in which this glyph appears in the source text
|
|
|
|
pub line: u64,
|
|
|
|
pub line: u64,
|
|
|
@ -13,7 +13,8 @@ pub struct Position {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Position {
|
|
|
|
impl Position {
|
|
|
|
pub fn start() -> Self {
|
|
|
|
/// The 0,0 position: the very first character of a document is at the 0,0 position
|
|
|
|
|
|
|
|
pub fn origin() -> Self {
|
|
|
|
Self { line: 0, column: 0 }
|
|
|
|
Self { line: 0, column: 0 }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -35,6 +36,18 @@ impl Position {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for Position {
|
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
|
|
|
|
write!(
|
|
|
|
|
|
|
|
f,
|
|
|
|
|
|
|
|
"({line}, {column})",
|
|
|
|
|
|
|
|
line = self.line,
|
|
|
|
|
|
|
|
column = self.column
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// A Glyph represents a character occurring at some specific position in some input text.
|
|
|
|
#[derive(PartialEq, Clone)]
|
|
|
|
#[derive(PartialEq, Clone)]
|
|
|
|
pub struct Glyph {
|
|
|
|
pub struct Glyph {
|
|
|
|
/// the unicode code point of the glyph
|
|
|
|
/// the unicode code point of the glyph
|
|
|
@ -50,10 +63,12 @@ pub struct Glyph {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Glyph {
|
|
|
|
impl Glyph {
|
|
|
|
|
|
|
|
/// checks to see whether or not the character for this glyph is a word character
|
|
|
|
pub fn is_word(&self) -> bool {
|
|
|
|
pub fn is_word(&self) -> bool {
|
|
|
|
self.glyph.is_alphanumeric() || self.glyph == '.'
|
|
|
|
self.glyph.is_alphanumeric() || self.glyph == '.'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// checks to see whether or not the character for this glyph is a glob character
|
|
|
|
pub fn is_glob(&self) -> bool {
|
|
|
|
pub fn is_glob(&self) -> bool {
|
|
|
|
self.is_word() || self.glyph == '*'
|
|
|
|
self.is_word() || self.glyph == '*'
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -75,9 +90,16 @@ impl fmt::Debug for Glyph {
|
|
|
|
/// iteration of [tokens](crate::lex::Token), Glyphs is responsible for the creation and iteration
|
|
|
|
/// iteration of [tokens](crate::lex::Token), Glyphs is responsible for the creation and iteration
|
|
|
|
/// of glyphs.
|
|
|
|
/// of glyphs.
|
|
|
|
pub struct Glyphs<'text> {
|
|
|
|
pub struct Glyphs<'text> {
|
|
|
|
|
|
|
|
/// the characters of the input text that we're interested in reading
|
|
|
|
source: Chars<'text>,
|
|
|
|
source: Chars<'text>,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// the position of the next character in the source text
|
|
|
|
next_position: Position,
|
|
|
|
next_position: Position,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// the number of bytes we've read from our input document so far
|
|
|
|
bytes_read: u64,
|
|
|
|
bytes_read: u64,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// lookahead buffer
|
|
|
|
lookahead: VecDeque<Glyph>,
|
|
|
|
lookahead: VecDeque<Glyph>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -86,7 +108,7 @@ impl<'text> Glyphs<'text> {
|
|
|
|
// neat
|
|
|
|
// neat
|
|
|
|
Self {
|
|
|
|
Self {
|
|
|
|
source: source.chars(),
|
|
|
|
source: source.chars(),
|
|
|
|
next_position: Position::start(),
|
|
|
|
next_position: Position::origin(),
|
|
|
|
bytes_read: 0,
|
|
|
|
bytes_read: 0,
|
|
|
|
lookahead: VecDeque::new(),
|
|
|
|
lookahead: VecDeque::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -157,6 +179,9 @@ impl<'text> Glyphs<'text> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// discards all of the upcoming whitespace characters. After calling yeet_whitespace, the next
|
|
|
|
|
|
|
|
/// Glyp is guaranteed to be either non-whitespace or None (None would be because we've hit
|
|
|
|
|
|
|
|
/// EOF)
|
|
|
|
pub fn yeet_whitespace(&mut self) {
|
|
|
|
pub fn yeet_whitespace(&mut self) {
|
|
|
|
self.yeet_while(|tg| tg.glyph.is_whitespace());
|
|
|
|
self.yeet_while(|tg| tg.glyph.is_whitespace());
|
|
|
|
}
|
|
|
|
}
|
|
|
|