1use erl_tokenize::tokens::{AtomToken, SymbolToken, VariableToken};
3use erl_tokenize::values::Symbol;
4use erl_tokenize::{LexicalToken, Position, PositionRange};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::mem;
8
9use crate::token_reader::{ReadFrom, TokenReader};
10use crate::{Error, Result};
11
12#[derive(Debug, Clone)]
14#[allow(missing_docs)]
15pub enum MacroName {
16 Atom(AtomToken),
17 Variable(VariableToken),
18}
19impl MacroName {
20 pub fn value(&self) -> &str {
22 match *self {
23 MacroName::Atom(ref t) => t.value(),
24 MacroName::Variable(ref t) => t.value(),
25 }
26 }
27
28 pub fn text(&self) -> &str {
30 match *self {
31 MacroName::Atom(ref t) => t.text(),
32 MacroName::Variable(ref t) => t.text(),
33 }
34 }
35}
36impl PartialEq for MacroName {
37 fn eq(&self, other: &Self) -> bool {
38 self.value() == other.value()
39 }
40}
41impl Eq for MacroName {}
42impl Hash for MacroName {
43 fn hash<H: Hasher>(&self, hasher: &mut H) {
44 self.value().hash(hasher);
45 }
46}
47impl PositionRange for MacroName {
48 fn start_position(&self) -> Position {
49 match *self {
50 MacroName::Atom(ref t) => t.start_position(),
51 MacroName::Variable(ref t) => t.start_position(),
52 }
53 }
54 fn end_position(&self) -> Position {
55 match *self {
56 MacroName::Atom(ref t) => t.end_position(),
57 MacroName::Variable(ref t) => t.end_position(),
58 }
59 }
60}
61impl fmt::Display for MacroName {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 write!(f, "{}", self.text())
64 }
65}
66impl ReadFrom for MacroName {
67 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
68 where
69 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
70 {
71 if let Some(token) = reader.try_read()? {
72 Ok(MacroName::Atom(token))
73 } else {
74 let token = reader.read()?;
75 Ok(MacroName::Variable(token))
76 }
77 }
78}
79
80#[derive(Debug, Clone)]
82#[allow(missing_docs)]
83pub struct MacroVariables {
84 pub _open_paren: SymbolToken,
85 pub list: List<VariableToken>,
86 pub _close_paren: SymbolToken,
87}
88impl MacroVariables {
89 pub fn iter(&self) -> ListIter<VariableToken> {
91 self.list.iter()
92 }
93
94 pub fn len(&self) -> usize {
96 self.list.iter().count()
97 }
98
99 pub fn is_empty(&self) -> bool {
101 self.len() == 0
102 }
103}
104impl PositionRange for MacroVariables {
105 fn start_position(&self) -> Position {
106 self._open_paren.start_position()
107 }
108 fn end_position(&self) -> Position {
109 self._close_paren.end_position()
110 }
111}
112impl fmt::Display for MacroVariables {
113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
114 write!(f, "({})", self.list)
115 }
116}
117impl ReadFrom for MacroVariables {
118 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
119 where
120 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
121 {
122 Ok(MacroVariables {
123 _open_paren: reader.read_expected(&Symbol::OpenParen)?,
124 list: reader.read()?,
125 _close_paren: reader.read_expected(&Symbol::CloseParen)?,
126 })
127 }
128}
129
130#[derive(Debug, Clone)]
132#[allow(missing_docs)]
133pub struct MacroArgs {
134 pub _open_paren: SymbolToken,
135 pub list: List<MacroArg>,
136 pub _close_paren: SymbolToken,
137}
138impl MacroArgs {
139 pub fn iter(&self) -> ListIter<MacroArg> {
141 self.list.iter()
142 }
143
144 pub fn len(&self) -> usize {
146 self.list.iter().count()
147 }
148
149 pub fn is_empty(&self) -> bool {
151 self.len() == 0
152 }
153}
154impl PositionRange for MacroArgs {
155 fn start_position(&self) -> Position {
156 self._open_paren.start_position()
157 }
158 fn end_position(&self) -> Position {
159 self._close_paren.end_position()
160 }
161}
162impl fmt::Display for MacroArgs {
163 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164 write!(f, "({})", self.list)
165 }
166}
167impl ReadFrom for MacroArgs {
168 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
169 where
170 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
171 {
172 Ok(MacroArgs {
173 _open_paren: reader.read_expected(&Symbol::OpenParen)?,
174 list: reader.read()?,
175 _close_paren: reader.read_expected(&Symbol::CloseParen)?,
176 })
177 }
178}
179
180#[derive(Debug, Clone)]
182pub struct MacroArg {
183 pub tokens: Vec<LexicalToken>,
187}
188impl PositionRange for MacroArg {
189 fn start_position(&self) -> Position {
190 self.tokens.first().as_ref().unwrap().start_position()
191 }
192 fn end_position(&self) -> Position {
193 self.tokens.last().as_ref().unwrap().end_position()
194 }
195}
196impl fmt::Display for MacroArg {
197 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
198 for t in &self.tokens {
199 write!(f, "{}", t.text())?;
200 }
201 Ok(())
202 }
203}
204impl ReadFrom for MacroArg {
205 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
206 where
207 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
208 {
209 let mut stack = Vec::new();
210 let mut arg = Vec::new();
211 while let Some(token) = reader.try_read_token()? {
212 if let LexicalToken::Symbol(ref s) = token {
213 match s.value() {
214 Symbol::CloseParen if stack.is_empty() => {
215 reader.unread_token(s.clone().into());
216 return if arg.is_empty() {
217 Err(Error::missing_macro_arg(s.start_position()))
218 } else {
219 Ok(MacroArg { tokens: arg })
220 };
221 }
222 Symbol::Comma if stack.is_empty() => {
223 if arg.is_empty() {
224 return Err(Error::missing_macro_arg(s.start_position()));
225 }
226 reader.unread_token(s.clone().into());
227 return Ok(MacroArg { tokens: arg });
228 }
229 Symbol::OpenParen
230 | Symbol::OpenBrace
231 | Symbol::OpenSquare
232 | Symbol::DoubleLeftAngle => {
233 stack.push(s.clone());
234 }
235 Symbol::CloseParen
236 | Symbol::CloseBrace
237 | Symbol::CloseSquare
238 | Symbol::DoubleRightAngle => {
239 let last = stack
240 .pop()
241 .ok_or_else(|| Error::unbalanced_paren(None, s.clone()))?;
242 let expected = match last.value() {
243 Symbol::OpenParen => Symbol::CloseParen,
244 Symbol::OpenBrace => Symbol::CloseBrace,
245 Symbol::OpenSquare => Symbol::CloseSquare,
246 Symbol::DoubleLeftAngle => Symbol::DoubleRightAngle,
247 _ => unreachable!(),
248 };
249 if s.value() != expected {
250 return Err(Error::unbalanced_paren(Some(last), s.clone()));
251 }
252 }
253 _ => {}
254 }
255 }
256 arg.push(token);
257 }
258 Err(Error::UnexpectedEof)
259 }
260}
261
262#[derive(Debug, Clone)]
264#[allow(missing_docs)]
265pub enum Tail<T> {
266 Null,
267 Cons {
268 _comma: SymbolToken,
269 head: T,
270 tail: Box<Tail<T>>,
271 },
272}
273impl<T: fmt::Display> fmt::Display for Tail<T> {
274 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
275 match *self {
276 Tail::Null => Ok(()),
277 Tail::Cons {
278 ref head, ref tail, ..
279 } => write!(f, ",{}{}", head, tail),
280 }
281 }
282}
283impl<U: ReadFrom> ReadFrom for Tail<U> {
284 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
285 where
286 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
287 {
288 if let Some(_comma) = reader.try_read_expected(&Symbol::Comma)? {
289 let head = reader.read()?;
290 let tail = Box::new(reader.read()?);
291 Ok(Tail::Cons { _comma, head, tail })
292 } else {
293 Ok(Tail::Null)
294 }
295 }
296}
297
298#[derive(Debug, Clone)]
300#[allow(missing_docs)]
301pub enum List<T> {
302 Null,
303 Cons { head: T, tail: Tail<T> },
304}
305impl<T> List<T> {
306 pub fn iter(&self) -> ListIter<T> {
308 ListIter(ListIterInner::List(self))
309 }
310}
311impl<T: fmt::Display> fmt::Display for List<T> {
312 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
313 match *self {
314 List::Null => Ok(()),
315 List::Cons { ref head, ref tail } => write!(f, "{}{}", head, tail),
316 }
317 }
318}
319impl<U: ReadFrom> ReadFrom for List<U> {
320 fn read_from<T>(reader: &mut TokenReader<T>) -> Result<Self>
321 where
322 T: Iterator<Item = erl_tokenize::Result<LexicalToken>>,
323 {
324 if let Some(head) = reader.try_read()? {
325 let tail = reader.read()?;
326 Ok(List::Cons { head, tail })
327 } else {
328 Ok(List::Null)
329 }
330 }
331}
332
333#[derive(Debug)]
335pub struct ListIter<'a, T: 'a>(ListIterInner<'a, T>);
336impl<'a, T: 'a> Iterator for ListIter<'a, T> {
337 type Item = &'a T;
338 fn next(&mut self) -> Option<Self::Item> {
339 self.0.next()
340 }
341}
342
343#[derive(Debug)]
344enum ListIterInner<'a, T: 'a> {
345 List(&'a List<T>),
346 Tail(&'a Tail<T>),
347 End,
348}
349impl<'a, T: 'a> Iterator for ListIterInner<'a, T> {
350 type Item = &'a T;
351 fn next(&mut self) -> Option<Self::Item> {
352 match mem::replace(self, ListIterInner::End) {
353 ListIterInner::List(&List::Cons { ref head, ref tail }) => {
354 *self = ListIterInner::Tail(tail);
355 Some(head)
356 }
357 ListIterInner::Tail(&Tail::Cons {
358 ref head, ref tail, ..
359 }) => {
360 *self = ListIterInner::Tail(tail);
361 Some(head)
362 }
363 ListIterInner::List(&List::Null)
364 | ListIterInner::Tail(&Tail::Null)
365 | ListIterInner::End => None,
366 }
367 }
368}