Initial commit with lexer
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
150
src/syn/span.rs
Normal file
150
src/syn/span.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Pos {
|
||||
pub source: usize,
|
||||
pub line: usize,
|
||||
pub col: usize,
|
||||
pub byte: usize,
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
impl Default for Pos {
|
||||
fn default() -> Self {
|
||||
Pos {
|
||||
source: 0,
|
||||
line: 0,
|
||||
col: 0,
|
||||
byte: 0,
|
||||
len: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pos {
|
||||
pub fn from_char(c: char, source: usize, line: usize, col: usize, byte: usize) -> Self {
|
||||
Pos {
|
||||
source, line, col, byte, len: c.len_utf8(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_char(&self, c: char) -> Self {
|
||||
Pos {
|
||||
source: self.source + 1,
|
||||
line: self.line,
|
||||
col: self.col + 1,
|
||||
byte: self.byte + self.len,
|
||||
len: c.len_utf8(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
if self.byte < other.byte {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
if self.byte > other.byte {
|
||||
self
|
||||
} else {
|
||||
other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
pub struct Span {
|
||||
pub start: Pos,
|
||||
pub end: Pos,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn union(self, other: Self) -> Self {
|
||||
let start = self.start.min(other.start);
|
||||
let end = self.end.max(other.end);
|
||||
Span { start, end }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Spanned {
|
||||
fn span(&self) -> Span;
|
||||
|
||||
fn text_at<'t>(&self, text: &'t str) -> &'t str {
|
||||
let Span { start, end } = self.span();
|
||||
&text[start.byte .. end.byte]
|
||||
}
|
||||
}
|
||||
|
||||
impl Spanned for Span {
|
||||
fn span(&self) -> Span {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_pos_min() {
|
||||
let small = Pos::default();
|
||||
let large = Pos {
|
||||
source: 1,
|
||||
byte: 1,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(small.min(large), small);
|
||||
assert_eq!(large.min(small), small);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pos_max() {
|
||||
let small = Pos::default();
|
||||
let large = Pos {
|
||||
source: 1,
|
||||
byte: 1,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
assert_eq!(small.max(large), large);
|
||||
assert_eq!(large.max(small), large);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_span_union() {
|
||||
let first = Span {
|
||||
start: Pos::default(),
|
||||
end: Pos {
|
||||
source: 15,
|
||||
col: 15,
|
||||
byte: 15,
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
|
||||
let second = Span {
|
||||
start: Pos {
|
||||
source: 25,
|
||||
col: 25,
|
||||
byte: 25,
|
||||
..Default::default()
|
||||
},
|
||||
end: Pos {
|
||||
source: 27,
|
||||
col: 27,
|
||||
byte: 27,
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
|
||||
let expected = Span {
|
||||
start: first.start,
|
||||
end: second.end,
|
||||
};
|
||||
|
||||
assert_eq!(first.union(second), expected);
|
||||
assert_eq!(second.union(first), expected);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user