1use super::error::SyntaxError;
2use super::error::SyntaxErrorType;
3use super::token::TokenType;
4use std::cmp::max;
5use std::cmp::min;
6use std::ops::Add;
7use std::ops::AddAssign;
8
9#[derive(Clone, Copy, Debug)]
10pub struct SourceRange {
11 start: u32,
12 end: u32,
13}
14
15impl SourceRange {
16 pub fn new(start: usize, end: usize) -> SourceRange {
17 debug_assert!(start <= end);
18 SourceRange {
19 start: start.try_into().unwrap(),
20 end: end.try_into().unwrap(),
21 }
22 }
23
24 pub fn start(&self) -> usize {
25 self.start.try_into().unwrap()
26 }
27
28 pub fn end(&self) -> usize {
29 self.end.try_into().unwrap()
30 }
31
32 pub fn at_start(&self) -> SourceRange {
33 SourceRange {
34 start: self.start,
35 end: self.start,
36 }
37 }
38
39 pub fn at_end(&self) -> SourceRange {
40 SourceRange {
41 start: self.end,
42 end: self.end,
43 }
44 }
45
46 pub fn error(self, typ: SyntaxErrorType, actual_token: Option<TokenType>) -> SyntaxError {
47 SyntaxError::from_loc(self, typ, actual_token)
48 }
49
50 pub fn add_option(self, rhs: Option<SourceRange>) -> SourceRange {
51 let mut new = self;
52 if let Some(rhs) = rhs {
53 new.extend(rhs);
54 };
55 new
56 }
57
58 pub fn is_empty(&self) -> bool {
59 self.end == self.start
60 }
61
62 pub fn len(&self) -> usize {
63 (self.end - self.start).try_into().unwrap()
64 }
65
66 pub fn extend(&mut self, other: SourceRange) {
67 self.start = min(self.start, other.start);
68 self.end = max(self.end, other.end);
69 }
70}
71
72impl Add for SourceRange {
73 type Output = SourceRange;
74
75 fn add(self, rhs: Self) -> Self::Output {
76 let mut new = self;
77 new.extend(rhs);
78 new
79 }
80}
81
82impl AddAssign for SourceRange {
83 fn add_assign(&mut self, rhs: Self) {
84 self.extend(rhs);
85 }
86}