1use std::fmt::{Debug, Display};
4
5#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
9pub struct LineColPos {
10 line: u16,
11 col: u16,
12}
13
14impl LineColPos {
15 pub fn new(line: u16, col: u16) -> Self {
17 Self { line, col }
18 }
19
20 pub fn dummy() -> Self {
22 Self::new(0, 0)
23 }
24
25 pub fn line(&self) -> u16 {
27 self.line
28 }
29
30 pub fn col(&self) -> u16 {
32 self.col
33 }
34}
35
36#[derive(Clone, Debug)]
38pub struct PosTbl {
39 chars: Vec<LineColPos>,
40}
41
42impl PosTbl {
43 pub fn new(chars: Vec<LineColPos>) -> Self {
45 Self { chars }
46 }
47
48 pub fn generate(src: impl Iterator<Item = char>) -> Self {
50 let mut buf = Vec::new();
51
52 let mut line = 0;
53 let mut chr = 0;
54
55 for c in src {
56 let lcp = if c == '\n' {
57 let p = LineColPos::new(line, chr);
58 line += 1;
59 chr = 0;
60 p
61 } else {
62 let p = LineColPos::new(line, chr);
63 chr += 1;
64 p
65 };
66
67 buf.push(lcp);
68 }
69
70 Self::new(buf)
71 }
72
73 pub fn get(&self, idx: usize) -> Option<LineColPos> {
75 self.chars.get(idx).copied()
76 }
77
78 pub fn get_srcpos(&self, idx: usize) -> Option<SrcPos> {
80 self.get(idx).map(|lcp| SrcPos::new(idx as i32, lcp))
81 }
82
83 pub fn expect_srcpos(&self, idx: usize) -> SrcPos {
85 self.get_srcpos(idx).expect("srcpos: out of bounds")
86 }
87
88 pub fn expect_end(&self) -> SrcPos {
90 let last_lcp = *self.chars.last().expect("srcpos: empty");
91 SrcPos::new(self.chars.len() as i32, last_lcp)
92 }
93}
94
95#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
97pub struct SrcPos {
98 off: i32,
100
101 lc: LineColPos,
103}
104
105impl SrcPos {
106 pub fn new(off: i32, lc: LineColPos) -> Self {
108 Self { off, lc }
109 }
110
111 pub fn dummy() -> Self {
113 Self::new(-1, LineColPos::dummy())
114 }
115
116 pub fn off(&self) -> i32 {
118 self.off
119 }
120
121 pub fn line_col_pos(&self) -> LineColPos {
123 self.lc
124 }
125
126 pub fn line(&self) -> u16 {
128 self.lc.line
129 }
130
131 pub fn col(&self) -> u16 {
133 self.lc.col
134 }
135}
136
137impl Display for SrcPos {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(f, "L{}:C{}", self.line(), self.col())
140 }
141}
142
143impl Debug for SrcPos {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "L{}:C{}:#{}", self.line(), self.col(), self.off())
146 }
147}
148
149#[derive(Copy, Clone, Debug, Eq, PartialEq)]
151pub struct SrcSpan {
152 start: SrcPos,
153 end: SrcPos,
154}
155
156impl SrcSpan {
157 pub fn new(start: SrcPos, end: SrcPos) -> Self {
159 Self { start, end }
160 }
161
162 pub fn start(&self) -> SrcPos {
164 self.start
165 }
166
167 pub fn end(&self) -> SrcPos {
169 self.end
170 }
171}