perl-lexer 0.16.0

High-performance Perl lexer with context-aware tokenization
Documentation
use crate::PerlLexer;

impl PerlLexer<'_> {
    #[inline]
    pub(crate) fn trailing_ws_only(bytes: &[u8], mut p: usize) -> bool {
        while let Some(&byte) = bytes.get(p) {
            if byte == b'\n' || byte == b'\r' {
                return true;
            }

            match byte {
                b' ' | b'\t' => p += 1,
                _ => return false,
            }
        }
        true
    }

    #[inline]
    pub(crate) fn consume_newline(&mut self) {
        if self.position >= self.input.len() {
            return;
        }

        match self.input_bytes[self.position] {
            b'\r' => {
                self.position += 1;
                if self.position < self.input.len() && self.input_bytes[self.position] == b'\n' {
                    self.position += 1;
                }
            }
            b'\n' => self.advance(),
            _ => return,
        }

        self.after_newline = true;
        self.line_start_offset = self.position;
    }

    #[inline]
    pub(crate) fn find_line_end(bytes: &[u8], start: usize) -> usize {
        if start >= bytes.len() {
            return start;
        }

        bytes[start..]
            .iter()
            .position(|&byte| byte == b'\n' || byte == b'\r')
            .map_or(bytes.len(), |offset| start + offset)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn trailing_ws_only_stops_at_newline() {
        let bytes = b"\t  \nnot checked";
        assert!(PerlLexer::trailing_ws_only(bytes, 0));
    }

    #[test]
    fn trailing_ws_only_rejects_non_whitespace_before_newline() {
        let bytes = b"\t x\n";
        assert!(!PerlLexer::trailing_ws_only(bytes, 0));
    }

    #[test]
    fn find_line_end_handles_crlf_and_bounds() {
        let bytes = b"first\r\nsecond";
        assert_eq!(PerlLexer::find_line_end(bytes, 0), 5);
        assert_eq!(PerlLexer::find_line_end(bytes, 7), 13);
        assert_eq!(PerlLexer::find_line_end(bytes, bytes.len()), 13);
        assert_eq!(PerlLexer::find_line_end(bytes, bytes.len() + 1), 14);
    }
}