1use std::{fmt};
2use std::ops::{Range};
3use std::str::{Chars};
4
5use super::{Tree, EndOfFile};
6
7#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
11pub struct Location {
12 pub start: usize,
14 pub end: usize,
16}
17
18impl Location {
19 pub const EVERYWHERE: Location = Location {start: usize::MIN, end: usize::MAX};
21}
22
23impl fmt::Debug for Location {
24 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25 write!(f, "{}..{}", self.start, self.end)
26 }
27}
28
29impl From<Range<usize>> for Location {
30 fn from(value: Range<usize>) -> Self { Self {start: value.start, end: value.end} }
31}
32
33#[derive(Copy, Clone)]
40pub struct Loc<T>(pub T, pub Location);
41
42impl<T> Loc<T> {
43 pub fn as_ref(&self) -> Loc<&T> { Loc(&self.0, self.1) }
45}
46
47impl<T: fmt::Debug> fmt::Debug for Loc<T> {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 self.0.fmt(f)?;
50 write!(f, " ({:?})", self.1)
51 }
52}
53
54impl<U, T: PartialEq<U>> PartialEq<U> for Loc<T> {
55 fn eq(&self, other: &U) -> bool { self.0 == *other }
56}
57
58#[derive(Debug)]
69pub struct Token(pub Loc<Result<Box<dyn Tree>, String>>);
70
71impl Token {
72 pub fn new(tree: Box<dyn Tree>, location: impl Into<Location>) -> Self {
74 Token(Loc(Ok(tree), location.into()))
75 }
76
77 pub fn new_err(message: impl Into<String>, location: impl Into<Location>) -> Self {
79 Token(Loc(Err(message.into()), location.into()))
80 }
81
82 pub fn end_of_file() -> Self { Self::new(Box::new(EndOfFile), Location::EVERYWHERE) }
84
85 pub fn incomplete() -> Self { Self::new_err("", Location::EVERYWHERE) }
87
88 pub fn location(&self) -> Location { self.0.1 }
90
91 pub fn result(self) -> Result<Box<dyn Tree>, String> { self.0.0 }
93
94 pub fn result_ref(&self) -> &Result<Box<dyn Tree>, String> { &self.0.0 }
96
97 pub fn is<T: Tree>(&self) -> bool {
99 if let Ok(t) = self.result_ref() { t.is::<T>() } else { false }
100 }
101
102 pub fn is_incomplete(&self) -> bool {
104 if let Err(e) = self.result_ref() { e.len() == 0 } else { false }
105 }
106
107 pub fn unwrap<T: Tree>(self) -> T {
112 *self.result().unwrap().downcast::<T>().unwrap()
113 }
114
115 pub fn unwrap_err(self) -> String {
119 self.result().unwrap_err()
120 }
121}
122
123impl<T: Tree + PartialEq> std::cmp::PartialEq<T> for Token {
124 fn eq(&self, other: &T) -> bool {
125 if let Ok(t) = self.result_ref() { **t == *other } else { false }
126 }
127}
128
129pub trait Stream {
137 fn read(&mut self) -> Token;
139
140 fn read_all(mut self) -> Vec<Token> where Self: Sized {
142 let mut ret = Vec::new();
143 let mut token = self.read();
144 while token != EndOfFile {
145 ret.push(token);
146 token = self.read();
147 }
148 ret
149 }
150}
151
152impl<I: Iterator<Item=Token>> Stream for I {
153 fn read(&mut self) -> Token {
154 self.next().unwrap_or_else(|| Token::end_of_file())
155 }
156}
157
158pub struct Characters<'a> {
167 chars: Chars<'a>,
169
170 length: usize,
172
173 is_complete: bool,
175}
176
177impl<'a> Characters<'a> {
178 pub fn new(source: &'a str, is_complete: bool) -> Self {
183 Self {chars: source.chars(), length: source.len(), is_complete}
184 }
185
186 pub fn index(&self) -> usize { self.length - self.chars.as_str().len() }
188}
189
190impl<'a> Stream for Characters<'a> {
191 fn read(&mut self) -> Token {
192 let start = self.index();
193 if let Some(c) = self.chars.next() {
194 let end = self.index();
195 Token::new(Box::new(c), start..end)
196 } else if self.is_complete { Token::end_of_file() } else { Token::incomplete() }
197 }
198}