ziyy-core 0.1.4

Terminal Styling using HTML-like syntax.
Documentation
pub use source::Source;

use crate::common::Span;

mod source;

pub fn is_alpha(c: char) -> bool {
    matches!(c, 'a'..='z' | 'A'..='Z' | '_')
}

pub fn is_digit(c: char) -> bool {
    c.is_ascii_digit()
}

pub fn is_alpha_numeric(c: char) -> bool {
    is_alpha(c) || is_digit(c)
}

pub fn is_hexdigit(c: char) -> bool {
    c.is_ascii_hexdigit()
}

pub trait GenericScanner<T: PartialEq, U> {
    fn source(&self) -> &impl Source<T>;
    fn tokens(&mut self) -> &mut Vec<U>;
    fn set_start(&mut self, n: usize);
    fn current(&self) -> usize;
    fn set_current(&mut self, n: usize);
    fn span(&mut self) -> &mut Span;
    fn scan_token(&mut self);

    fn scan_tokens<'a>(&'a mut self) -> Vec<U>
    where
        T: 'a,
    {
        while !self.is_at_end() {
            self.set_start(self.current());
            self.scan_token();
        }

        std::mem::take(self.tokens())
    }

    fn peek(&self) -> T {
        if self.is_at_end() {
            self.source().null()
        } else {
            self.source().at(self.current())
        }
    }

    fn peek_next(&self) -> T {
        if self.current() + 1 > self.source().len() {
            self.source().null()
        } else {
            self.source().at(self.current() + 1)
        }
    }

    fn is_at_end(&self) -> bool {
        self.current() >= self.source().len()
    }

    fn advance(&mut self) -> T {
        self.set_current(self.current() + 1);
        *self.span() += (0, 1);
        let ch = self.source().at(self.current() - 1);
        if ch == self.source().nl() {
            *self.span() += (1, 0);
        }
        ch
    }
}

macro_rules! impl_generic_scanner {
    ( $f:expr ) => {
        impl GenericScanner<char, Token> for Scanner {
            fn source(&self) -> &impl Source<char> {
                &self.source
            }

            fn tokens(&mut self) -> &mut Vec<Token> {
                &mut self.tokens
            }

            fn set_start(&mut self, n: usize) {
                self.start = n;
            }

            fn current(&self) -> usize {
                self.current
            }

            fn set_current(&mut self, n: usize) {
                self.current = n;
            }

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

            fn scan_token(&mut self) {
                $f(self);
            }
        }
    };
}