erl_parse/cst/
literal.rs

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}