Skip to content

Commit 8809a0d

Browse files
committed
Add span struct representing a continious parsed span
1 parent ea0eb1b commit 8809a0d

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub mod ast;
4444
pub mod dialect;
4545
pub mod keywords;
4646
pub mod parser;
47+
pub mod span;
4748
pub mod tokenizer;
4849

4950
#[doc(hidden)]

src/span.rs

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#[derive(Debug, Eq, Clone, Copy)]
2+
pub enum Span {
3+
Unset,
4+
Set { start: usize, end: usize },
5+
}
6+
7+
/// All spans are equal
8+
impl PartialEq for Span {
9+
fn eq(&self, _: &Self) -> bool {
10+
return true;
11+
}
12+
}
13+
14+
/// All spans hash to the same value
15+
impl core::hash::Hash for Span {
16+
fn hash<H: std::hash::Hasher>(&self, _: &mut H) {}
17+
}
18+
19+
impl Span {
20+
pub fn new() -> Self {
21+
Span::Unset
22+
}
23+
24+
pub fn expanded(&self, item: &impl Spanned) -> Span {
25+
match self {
26+
Span::Unset => item.span(),
27+
Span::Set { start: s1, end: e1 } => match item.span() {
28+
Span::Unset => *self,
29+
Span::Set { start: s2, end: e2 } => {
30+
(usize::min(*s1, s2)..usize::max(*e1, e2)).into()
31+
}
32+
},
33+
}
34+
}
35+
36+
pub fn expand(&mut self, item: &impl Spanned) {
37+
*self = self.expanded(item);
38+
}
39+
40+
pub fn start(&self) -> Option<usize> {
41+
match self {
42+
Span::Unset => None,
43+
Span::Set { start, .. } => Some(*start),
44+
}
45+
}
46+
47+
pub fn end(&self) -> Option<usize> {
48+
match self {
49+
Span::Unset => None,
50+
Span::Set { end, .. } => Some(*end),
51+
}
52+
}
53+
54+
pub fn range(&self) -> Option<core::ops::Range<usize>> {
55+
match self {
56+
Span::Unset => None,
57+
Span::Set { start, end } => Some(*start..*end),
58+
}
59+
}
60+
}
61+
62+
impl Default for Span {
63+
fn default() -> Self {
64+
Span::Unset
65+
}
66+
}
67+
68+
impl core::convert::From<core::ops::Range<usize>> for Span {
69+
fn from(r: core::ops::Range<usize>) -> Self {
70+
Self::Set {
71+
start: r.start,
72+
end: r.end,
73+
}
74+
}
75+
}
76+
77+
pub struct UnsetSpanError;
78+
79+
impl core::convert::TryInto<core::ops::Range<usize>> for Span {
80+
type Error = UnsetSpanError;
81+
82+
fn try_into(self) -> Result<core::ops::Range<usize>, Self::Error> {
83+
match self {
84+
Span::Unset => Err(UnsetSpanError),
85+
Span::Set { start, end } => Ok(start..end),
86+
}
87+
}
88+
}
89+
90+
pub trait Spanned {
91+
fn span(&self) -> Span;
92+
}
93+
94+
impl Spanned for Span {
95+
fn span(&self) -> Span {
96+
self.clone()
97+
}
98+
}
99+
100+
impl<T: Spanned> Spanned for Option<T> {
101+
fn span(&self) -> Span {
102+
match self {
103+
Some(v) => v.span(),
104+
None => Default::default(),
105+
}
106+
}
107+
}
108+
109+
impl<T: Spanned> Spanned for Vec<T> {
110+
fn span(&self) -> Span {
111+
let mut ans = Span::new();
112+
for v in self {
113+
ans.expand(v);
114+
}
115+
ans
116+
}
117+
}
118+
119+
impl<T: Spanned> Spanned for Box<T> {
120+
fn span(&self) -> Span {
121+
self.as_ref().span()
122+
}
123+
}

0 commit comments

Comments
 (0)