utterance 0.1.4

A parser library for creating readable, natural-language-inspired domain-specific languages.
Documentation
use std::fmt;

use crate::lexer::{Number, TokenType};
use crate::syntax::Span;

#[derive(Debug, Clone)]
pub struct Token<'a> {
    span: Span,
    token_type: TokenType<'a>,
}

impl<'a> Token<'a> {
    pub(crate) fn new(position: usize, token: &'a str) -> Self {
        assert!(!token.is_empty());

        let token_type = TokenType::Word(token);
        let span = Span::new(position, position + token.len());

        Self { span, token_type }
    }

    pub(crate) fn new_number(position: usize, number: Number, len: usize) -> Self {
        let span = Span::new(position, position + len);

        Self {
            span,
            token_type: TokenType::Number(number),
        }
    }

    pub(crate) fn new_hardcoded(position: usize, token_type: TokenType<'a>) -> Self {
        let len = match token_type {
            TokenType::End | TokenType::Newline => 0,

            TokenType::Symbol(_) => 1,
            TokenType::DoubleSymbol(_) => 2,

            TokenType::Word(_) | TokenType::Number(_) => unreachable!(),
        };

        let span = Span::new(position, position + len);

        Self { span, token_type }
    }

    pub fn token_type(&self) -> &TokenType<'a> {
        &self.token_type
    }

    pub fn span(&self) -> Span {
        self.span
    }
}

impl<'a> fmt::Display for Token<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self.token_type {
            TokenType::Word(text) => write!(f, "{text}"),
            TokenType::Number(value) => write!(f, "{value}"),
            TokenType::Symbol(symbol) => write!(f, "{symbol}"),
            TokenType::DoubleSymbol(symbol) => write!(f, "{symbol}{symbol}"),
            TokenType::Newline => write!(f, "\\n"),
            TokenType::End => write!(f, "<end>"),
        }
    }
}