erl_parse 0.0.8

Erlang source code parser
Documentation
use erl_tokenize::tokens::{AtomToken, CharToken, FloatToken, IntegerToken, StringToken};
use erl_tokenize::{LexicalToken, Position, PositionRange};

use crate::traits::{Parse, TokenRead};
use crate::{ErrorKind, Parser, Result};

#[derive(Debug, Clone)]
pub enum Literal {
    Atom(AtomToken),
    Char(CharToken),
    Float(FloatToken),
    Integer(IntegerToken),
    String {
        head: StringToken,
        tail: Vec<StringToken>,
    },
}
impl Parse for Literal {
    fn parse<T>(parser: &mut Parser<T>) -> Result<Self>
    where
        T: TokenRead,
    {
        match track!(parser.parse())? {
            LexicalToken::Atom(t) => Ok(Literal::Atom(t)),
            LexicalToken::Char(t) => Ok(Literal::Char(t)),
            LexicalToken::Float(t) => Ok(Literal::Float(t)),
            LexicalToken::Integer(t) => Ok(Literal::Integer(t)),
            LexicalToken::String(head) => {
                let mut tail = Vec::new();
                while let Ok(t) = parser.transaction(Parser::parse) {
                    tail.push(t);
                }
                Ok(Literal::String { head, tail })
            }
            token => track_panic!(ErrorKind::UnexpectedToken(token)),
        }
    }
}
impl PositionRange for Literal {
    fn start_position(&self) -> Position {
        match *self {
            Literal::Atom(ref x) => x.start_position(),
            Literal::Char(ref x) => x.start_position(),
            Literal::Float(ref x) => x.start_position(),
            Literal::Integer(ref x) => x.start_position(),
            Literal::String { ref head, .. } => head.start_position(),
        }
    }
    fn end_position(&self) -> Position {
        match *self {
            Literal::Atom(ref x) => x.end_position(),
            Literal::Char(ref x) => x.end_position(),
            Literal::Float(ref x) => x.end_position(),
            Literal::Integer(ref x) => x.end_position(),
            Literal::String { ref head, ref tail } => tail
                .last()
                .map(PositionRange::end_position)
                .unwrap_or_else(|| head.end_position()),
        }
    }
}