1use erl_tokenize::tokens::{AtomToken, CharToken, FloatToken, IntegerToken, StringToken};
2use erl_tokenize::{LexicalToken, Position, PositionRange};
3
4use crate::traits::{Parse, TokenRead};
5use crate::{ErrorKind, Parser, Result};
6
7#[derive(Debug, Clone)]
8pub enum Literal {
9 Atom(AtomToken),
10 Char(CharToken),
11 Float(FloatToken),
12 Integer(IntegerToken),
13 String {
14 head: StringToken,
15 tail: Vec<StringToken>,
16 },
17}
18impl Parse for Literal {
19 fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
20 where
21 T: TokenRead,
22 {
23 match track!(parser.parse())? {
24 LexicalToken::Atom(t) => Ok(Literal::Atom(t)),
25 LexicalToken::Char(t) => Ok(Literal::Char(t)),
26 LexicalToken::Float(t) => Ok(Literal::Float(t)),
27 LexicalToken::Integer(t) => Ok(Literal::Integer(t)),
28 LexicalToken::String(head) => {
29 let mut tail = Vec::new();
30 while let Ok(t) = parser.transaction(Parser::parse) {
31 tail.push(t);
32 }
33 Ok(Literal::String { head, tail })
34 }
35 token => track_panic!(ErrorKind::UnexpectedToken(token)),
36 }
37 }
38}
39impl PositionRange for Literal {
40 fn start_position(&self) -> Position {
41 match *self {
42 Literal::Atom(ref x) => x.start_position(),
43 Literal::Char(ref x) => x.start_position(),
44 Literal::Float(ref x) => x.start_position(),
45 Literal::Integer(ref x) => x.start_position(),
46 Literal::String { ref head, .. } => head.start_position(),
47 }
48 }
49 fn end_position(&self) -> Position {
50 match *self {
51 Literal::Atom(ref x) => x.end_position(),
52 Literal::Char(ref x) => x.end_position(),
53 Literal::Float(ref x) => x.end_position(),
54 Literal::Integer(ref x) => x.end_position(),
55 Literal::String { ref head, ref tail } => tail
56 .last()
57 .map(PositionRange::end_position)
58 .unwrap_or_else(|| head.end_position()),
59 }
60 }
61}