ast-description-lang 0.4.0

A language to describe your language's AST
Documentation
use std::cell::Cell;

#[derive(Clone)]
pub struct Lexer<'l> {
  text: &'l str,
  start: Cell<usize>,
  index: Cell<usize>,
}

impl<'l> Lexer<'l> {
  pub fn new(text: &str) -> Lexer {
    Lexer {
      text,
      start: Cell::new(0),
      index: Cell::new(0),
    }
  }

  pub fn text(&self) -> &str {
    self.text
  }

  pub fn index(&self) -> usize {
    self.index.get()
  }

  pub fn extract(&self) -> Option<&'l str> {
    let val = (self.start < self.index).then(|| &self.text[self.start.get()..self.index.get()]);
    self.start.set(self.index.get());
    val
  }

  pub fn peek(&self) -> Option<char> {
    (self.index.get() < self.text.len()).then(|| self.text.as_bytes()[self.index.get()] as char)
  }

  pub fn skip_whitespace(&self) {
    self.bump_while(|c| " \\\n\r\t".contains(c));
    self.start.set(self.index.get());
  }

  #[must_use]
  pub fn parse_literal(&self, value: &str) -> bool {
    let old_idx = self.index.get();
    for i in 0..value.len() {
      if self
        .peek()
        .map_or(false, |c| value.as_bytes()[i] as char == c)
      {
        self.increment();
      } else {
        self.index.set(old_idx);
        return false;
      }
    }
    self.start.set(self.index.get());
    true
  }

  pub fn bump_while(&self, f: fn(char) -> bool) {
    while self.peek().map_or(false, f) {
      self.increment()
    }
  }

  fn increment(&self) {
    self.index.set(self.index.get() + 1);
  }
}