fluid-parser 0.1.16

A fluid (fltk ui designer) file parser
Documentation
use crate::error::Location;
use crate::token::{Token, TokenType};

pub struct Lexer<'a> {
    pub s: &'a str,
    size: usize,
    cursor: usize,
    line: usize,
    col: usize,
}

impl<'a> Lexer<'a> {
    pub fn new(source: &str) -> Lexer {
        let size = source.len();
        let mut cursor = 0;
        let mut line = 1;
        let mut col = 1;
        if source.starts_with("# ") {
            while cursor < size && source.as_bytes()[cursor] != b'\n' {
                cursor += 1;
                col += 1;
            }
            if cursor < size && source.as_bytes()[cursor] == b'\n' {
                cursor += 1;
                line += 1;
                col = 1;
            }
        }
        Lexer {
            s: source,
            size,
            cursor,
            line,
            col,
        }
    }

    #[allow(clippy::should_implement_trait)]
    pub fn next(&mut self) -> Token<'a> {
        let mut t = Token::<'_> {
            loc: Location {
                line: self.line,
                col: self.col,
            },
            ..Default::default()
        };
        if self.cursor == self.size {
            t.typ = TokenType::Eof;
            t.start = self.size;
            t.end = self.size;
            return t;
        }
        while self.cursor < self.size
            && (self.s.as_bytes()[self.cursor] == b' '
                || self.s.as_bytes()[self.cursor] == b'\n'
                || self.s.as_bytes()[self.cursor] == b'\r'
                || self.s.as_bytes()[self.cursor] == b'\t')
        {
            if self.s.as_bytes()[self.cursor] == b'\n' {
                self.line += 1;
                self.col = 1;
            } else {
                self.col += 1;
            }
            self.cursor += 1;
        }
        if self.cursor == self.size {
            t.typ = TokenType::Eof;
            t.start = self.size;
            t.end = self.size;
            return t;
        }
        t.loc = Location {
            line: self.line,
            col: self.col,
        };
        match self.s.as_bytes()[self.cursor] {
            b'{' => {
                t.typ = TokenType::OpenBrace;
                t.start = self.cursor;
                t.end = self.cursor + 1;
                self.cursor += 1;
                self.col += 1;
                t
            }
            b'}' => {
                t.typ = TokenType::CloseBrace;
                t.start = self.cursor;
                t.end = self.cursor + 1;
                self.cursor += 1;
                self.col += 1;
                t
            }
            _ => {
                t.typ = TokenType::Word;

                t.start = self.cursor;
                while self.cursor < self.size
                    && self.s.as_bytes()[self.cursor] != b' '
                    && self.s.as_bytes()[self.cursor] != b'\n'
                    && self.s.as_bytes()[self.cursor] != b'\r'
                    && self.s.as_bytes()[self.cursor] != b'\t'
                    && self.s.as_bytes()[self.cursor] != b'}'
                {
                    self.cursor += 1;
                    self.col += 1;
                }
                t.end = self.cursor;
                t.word = &self.s[t.start..t.end];
                t
            }
        }
    }
}