tree-sitter-markdown-updated 0.1.0

Markdown grammar for tree-sitter
Documentation
#include "./lexer.h"

#include <cstring>
#include "./predicate.h"

namespace tree_sitter_markdown {

LexedIndex Lexer::cur_idx() const { return cur_idx_; }
LexedRow Lexer::cur_row() const { return cur_row_; }
LexedColumn Lexer::cur_col() const { return cur_col_; }
LexedPosition Lexer::cur_pos() const { return LexedPosition(cur_idx_, cur_row_, cur_col_); }
LexedPosition Lexer::cur_pos(const LexedIndex offset_idx) const { return LexedPosition(cur_idx_ + offset_idx, cur_row_, cur_col_ + offset_idx); }
LexedCharacter Lexer::cur_chr() const { return cur_chr_; }
LexedCharacter Lexer::lka_chr() const { return lka_chr_; }
LexedLength Lexer::cur_spc() const { return cur_spc_; }
LexedColumn Lexer::cur_ind() const { return cur_ind_; }

void Lexer::clear() {
  bgn_chr_ = 0;
  bgn_col_ = 0;
}
void Lexer::init(TSLexer *lexer) {
  lxr_ = lexer;
  cur_idx_ = 0;
  cur_row_ = 0;
  cur_col_ = bgn_col_;
  end_col_ = LEXED_INDEX_MAX;
  cur_chr_ = bgn_chr_;
  lka_chr_ = lexer->lookahead;
  end_chr_ = LEXED_CHARACTER_MAX;
  buf_bgn_idx_ = LEXED_INDEX_MAX;
  chr_buf_.clear();
  cur_spc_ = 0;
  cur_ind_ = 0;
  ind_chr_col_buf_.clear();
  is_rec_tbl_col_cnt_ = false;
}
void Lexer::mrk_end() {
  end_col_ = cur_col_;
  end_chr_ = cur_chr_;
  lxr_->mark_end(lxr_);
}

unsigned Lexer::serialize(unsigned char *buffer) {
  size_t i = 0;
  memcpy(&buffer[i], &bgn_col_, sizeof bgn_col_);
  i += sizeof bgn_col_;
  memcpy(&buffer[i], &bgn_chr_, sizeof bgn_chr_);
  i += sizeof bgn_chr_;
  return i;
}
unsigned Lexer::deserialize(const unsigned char *buffer) {
  size_t i = 0;
  memcpy(&bgn_col_, &buffer[i], sizeof bgn_col_);
  i += sizeof bgn_col_;
  memcpy(&bgn_chr_, &buffer[i], sizeof bgn_chr_);
  i += sizeof bgn_chr_;
  return i;
}

void Lexer::adv(const bool skp) {
  if (lka_chr_ == '\n' || lka_chr_ == '\r') {
    cur_col_ = 0;
    cur_ind_ = 0;
    ind_chr_col_buf_.clear();
  } else if (lka_chr_ == '\t') {
    LexedColumn offset = 4 - (cur_col_ % 4);
    cur_col_ += offset;
    cur_ind_ += offset;
    ind_chr_col_buf_.push_back(offset);
  } else if (lka_chr_ == ' ') {
    cur_col_++;
    cur_ind_++;
    ind_chr_col_buf_.push_back(1);
  } else {
    cur_col_++;
    cur_ind_ = 0;
    ind_chr_col_buf_.clear();
  }

  if (
    lka_chr_ == '\r'
    || (lka_chr_ == '\n' && cur_chr_ != '\r')
  ) cur_row_++;

  if (is_rec_tbl_col_cnt_ && !is_wsp_chr(lka_chr_)) {
    if (lka_chr_ == '|' && cur_chr_ != '\\') {
      if (tbl_col_is_bgn_) tbl_col_has_bgn_pip_ = true;
      tbl_col_pip_cnt_++;
      tbl_col_has_ctn_ = false;
    } else {
      tbl_col_has_ctn_ = true;
    }
    tbl_col_is_bgn_ = false;
  }

  if (lka_chr_ == ' ') cur_spc_++;
  else cur_spc_ = 0;

  cur_idx_++;
  cur_chr_ = lka_chr_;
  if (buf_bgn_idx_ == LEXED_INDEX_MAX) {
    lxr_->advance(lxr_, skp);
    lka_chr_ = lxr_->lookahead;
  } else {
    if (cur_idx_ - buf_bgn_idx_ + 1 >= chr_buf_.size()) {
      lxr_->advance(lxr_, skp);
      chr_buf_.push_back(lxr_->lookahead);
    }
    lka_chr_ = chr_buf_[cur_idx_ - buf_bgn_idx_ + 1];
  }
}
void Lexer::adv_len(const LexedLength len, const bool skp) {
  for (LexedLength i = 0; i < len; i++) adv(skp);
}
bool Lexer::adv_if(const LexedCharacter chr, const bool skp) {
  if (lka_chr_ != chr) return false;
  adv(skp);
  return true;
}
bool Lexer::adv_if(bool (*is_chr)(LexedCharacter), const bool skp) {
  if (!is_chr(lka_chr_)) return false;
  adv(skp);
  return true;
}
bool Lexer::adv_til(const LexedCharacter chr, const bool skp) {
  if (lka_chr_ == chr) return false;
  do adv(skp);
  while (lka_chr_ != chr);
  return true;
}
bool Lexer::adv_til(bool (*is_chr)(LexedCharacter), const bool skp) {
  if (is_chr(lka_chr_)) return false;
  do adv(skp);
  while (!is_chr(lka_chr_));
  return true;
}
bool Lexer::adv_rpt(const LexedCharacter chr, const bool skp) {
  bool has_chr = lka_chr_ == chr;
  if (has_chr) {
    do adv(skp);
    while (lka_chr_ == chr);
  }
  return has_chr;
}
bool Lexer::adv_rpt(bool (*is_chr)(LexedCharacter), const bool skp) {
  bool has_chr = is_chr(lka_chr_);
  if (has_chr) {
    do adv(skp);
    while (is_chr(lka_chr_));
  }
  return has_chr;
}
LexedLength Lexer::adv_rpt_len(const LexedCharacter chr, const LexedLength max_len, const bool skp) {
  LexedLength i = 0;
  for (; lka_chr_ == chr && i < max_len; i++) adv(skp);
  return i;
}
LexedLength Lexer::adv_rpt_len(bool (*is_chr)(LexedCharacter), const LexedLength max_len, const bool skp) {
  LexedLength i = 0;
  for (; is_chr(lka_chr_) && i < max_len; i++) adv(skp);
  return i;
}

void Lexer::bgn_buf() {
  TREE_SITTER_MARKDOWN_ASSERT(buf_bgn_idx_ == LEXED_INDEX_MAX);
  buf_bgn_idx_ = cur_idx_;
  chr_buf_.push_back(cur_chr_);
  chr_buf_.push_back(lka_chr_);
}
void Lexer::jmp_pos(const LexedPosition &pos) {
  if (pos.idx() == cur_idx_) return;
  TREE_SITTER_MARKDOWN_ASSERT(pos.idx() >= buf_bgn_idx_);
  TREE_SITTER_MARKDOWN_ASSERT(pos.idx() - buf_bgn_idx_ < chr_buf_.size() - 1);
  cur_idx_ = pos.idx();
  cur_row_ = pos.row();
  cur_col_ = pos.col();
  cur_chr_ = chr_buf_[cur_idx_ - buf_bgn_idx_];
  lka_chr_ = chr_buf_[cur_idx_ - buf_bgn_idx_ + 1];
  cur_spc_ = 0;
  cur_ind_ = 0;
}
bool Lexer::has_chr_at_idx(const LexedCharacter chr, const LexedIndex idx) const {
  TREE_SITTER_MARKDOWN_ASSERT(idx >= buf_bgn_idx_);
  TREE_SITTER_MARKDOWN_ASSERT(idx - buf_bgn_idx_ < chr_buf_.size());
  return idx < 0 ? false : chr_buf_[idx - buf_bgn_idx_] == chr;
}
bool Lexer::has_chr_at_idx(bool (*is_chr)(LexedCharacter), const LexedIndex idx) const {
  TREE_SITTER_MARKDOWN_ASSERT(idx >= buf_bgn_idx_);
  TREE_SITTER_MARKDOWN_ASSERT(idx - buf_bgn_idx_ < chr_buf_.size());
  return idx < 0 ? false : is_chr(chr_buf_[idx - buf_bgn_idx_]);
}
bool Lexer::has_chr_in_rng(bool (*is_chr)(LexedCharacter), const LexedIndex idx, const LexedIndex end_idx) const {
  TREE_SITTER_MARKDOWN_ASSERT(idx >= buf_bgn_idx_);
  TREE_SITTER_MARKDOWN_ASSERT(idx - buf_bgn_idx_ <= end_idx);
  TREE_SITTER_MARKDOWN_ASSERT(end_idx - buf_bgn_idx_ < chr_buf_.size() - 1);
  for (LexedIndex i = idx - buf_bgn_idx_; i < end_idx - buf_bgn_idx_; i++) {
    if (is_chr(chr_buf_[i])) return true;
  }
  return false;
}
bool Lexer::has_chr_in_rng(bool (*is_chr)(LexedCharacter), const LexedPosition pos, const LexedPosition end_pos) const {
  return has_chr_in_rng(is_chr, pos.idx(), end_pos.idx());
}

void Lexer::bgn_rec_tbl_col_cnt() {
  TREE_SITTER_MARKDOWN_ASSERT(!is_rec_tbl_col_cnt_);
  is_rec_tbl_col_cnt_ = true;
  tbl_col_is_bgn_ = true;
  tbl_col_has_bgn_pip_ = false;
  tbl_col_has_ctn_ = false;
  tbl_col_pip_cnt_ = 0;
}
void Lexer::end_rec_tbl_col_cnt() {
  TREE_SITTER_MARKDOWN_ASSERT(is_rec_tbl_col_cnt_);
  is_rec_tbl_col_cnt_ = false;
}
uint16_t Lexer::tbl_col_cnt() {
  TREE_SITTER_MARKDOWN_ASSERT(is_rec_tbl_col_cnt_);
  uint16_t tbl_col_cnt_ = tbl_col_pip_cnt_ + 1;
  if (tbl_col_has_bgn_pip_) tbl_col_cnt_--;
  bool has_end_pip = (tbl_col_pip_cnt_ - tbl_col_has_bgn_pip_) && !tbl_col_has_ctn_;
  if (has_end_pip) tbl_col_cnt_--;
  return tbl_col_cnt_;
}

LexedLength Lexer::clc_vtr_spc_cnt(const LexedColumn cur_ind, const LexedColumn tgt_ind, LexedLength &ind_chr_cnt_btw_cur_and_tgt) const {
  const LexedColumn actual_tgt_ind = cur_ind_ - cur_ind + tgt_ind;
  if (actual_tgt_ind == 0) {
    ind_chr_cnt_btw_cur_and_tgt = 0;
    return 0;
  }
  LexedColumn ind = 0;
  for (uint16_t i = 0; i < ind_chr_col_buf_.size(); i++) {
    ind += ind_chr_col_buf_[i];
    if (ind >= actual_tgt_ind) {
      ind_chr_cnt_btw_cur_and_tgt = i + 1;
      return ind - actual_tgt_ind;
    }
  }
  TREE_SITTER_MARKDOWN_ASSERT(false);
}

bool Lexer::ret_sym(const TokenType rlt_sym) {
  TREE_SITTER_MARKDOWN_ASSERT(end_col_ != LEXED_COLUMN_MAX);
  bgn_col_ = end_col_;
  TREE_SITTER_MARKDOWN_ASSERT(end_chr_ != LEXED_CHARACTER_MAX);
  bgn_chr_ = end_chr_;
  lxr_->result_symbol = rlt_sym;
  return true;
}

}