1use std::convert::From;
3use std::iter::Iterator;
4use std::path::PathBuf;
5
6use abortable_parser::iter::{SliceIter, StrIter};
7use abortable_parser::{InputIter, Offsetable, Peekable, Positioned, Seekable, Span, SpanRange};
8
9use crate::ast::{Position, Token};
10
11#[derive(Debug)]
12pub struct OffsetStrIter<'a> {
13 source_file: Option<PathBuf>,
14 contained: StrIter<'a>,
15 line_offset: usize,
16 col_offset: usize,
17}
18
19impl<'a> OffsetStrIter<'a> {
20 pub fn new(input: &'a str) -> Self {
21 Self::new_with_offsets(input, 0, 0)
22 }
23
24 pub fn new_with_offsets(input: &'a str, line_offset: usize, col_offset: usize) -> Self {
25 OffsetStrIter {
26 source_file: None,
27 contained: StrIter::new(input),
28 line_offset: line_offset,
29 col_offset: col_offset,
30 }
31 }
32
33 pub fn with_src_file<P: Into<PathBuf>>(mut self, file: P) -> Self {
34 self.source_file = Some(file.into());
35 self
36 }
37}
38
39impl<'a> Iterator for OffsetStrIter<'a> {
40 type Item = &'a u8;
41
42 fn next(&mut self) -> Option<Self::Item> {
43 self.contained.next()
44 }
45}
46
47impl<'a> Offsetable for OffsetStrIter<'a> {
48 fn get_offset(&self) -> usize {
49 self.contained.get_offset()
50 }
51}
52
53impl<'a> Clone for OffsetStrIter<'a> {
54 fn clone(&self) -> Self {
55 OffsetStrIter {
56 source_file: self.source_file.clone(),
57 contained: self.contained.clone(),
58 line_offset: self.line_offset,
59 col_offset: self.col_offset,
60 }
61 }
62}
63
64impl<'a> From<&'a str> for OffsetStrIter<'a> {
65 fn from(source: &'a str) -> Self {
66 OffsetStrIter {
67 source_file: None,
68 contained: StrIter::new(source),
69 line_offset: 0,
70 col_offset: 0,
71 }
72 }
73}
74
75impl<'a> Seekable for OffsetStrIter<'a> {
76 fn seek(&mut self, to: usize) -> usize {
77 self.contained.seek(to)
78 }
79}
80
81impl<'a> Span<&'a str> for OffsetStrIter<'a> {
82 fn span(&self, idx: SpanRange) -> &'a str {
83 self.contained.span(idx)
84 }
85}
86
87impl<'a> Peekable<&'a u8> for OffsetStrIter<'a> {
88 fn peek_next(&self) -> Option<&'a u8> {
89 self.contained.peek_next()
90 }
91}
92
93impl<'a> Positioned for OffsetStrIter<'a> {
94 fn line(&self) -> usize {
95 self.contained.line() + self.line_offset
96 }
97
98 fn column(&self) -> usize {
99 self.contained.column() + self.col_offset
100 }
101}
102
103impl<'a> InputIter for OffsetStrIter<'a> {
104 fn curr(&self) -> Self::Item {
105 self.clone().peek_next().unwrap()
106 }
107}
108
109impl<'a> From<&'a SliceIter<'a, Token>> for Position {
110 fn from(source: &'a SliceIter<'a, Token>) -> Self {
111 match source.peek_next() {
112 Some(t) => t.pos.clone(),
113 None => source.curr().pos.clone(),
114 }
115 }
116}
117
118impl<'a> From<&'a OffsetStrIter<'a>> for Position {
119 fn from(s: &'a OffsetStrIter<'a>) -> Position {
120 Position {
121 file: s.source_file.clone(),
122 line: s.line(),
123 column: s.column(),
124 offset: s.get_offset(),
125 }
126 }
127}
128
129pub trait FilePositioned: Positioned {
130 fn file(&self) -> Option<&PathBuf>;
131}
132
133impl<'a> FilePositioned for OffsetStrIter<'a> {
134 fn file(&self) -> Option<&PathBuf> {
135 self.source_file.as_ref()
136 }
137}
138
139impl<'a> FilePositioned for SliceIter<'a, Token> {
140 fn file(&self) -> Option<&PathBuf> {
141 match self.peek_next() {
142 Some(t) => t.pos.file.as_ref(),
143 None => None,
144 }
145 }
146}