Function: treesit-parser-create

treesit-parser-create is a function defined in treesit.c.

Signature

(treesit-parser-create LANGUAGE &optional BUFFER NO-REUSE TAG)

Documentation

Create and return a parser in BUFFER for LANGUAGE with TAG.

The parser is automatically added to BUFFER's parser list, as returned by treesit-parser-list. LANGUAGE is a language symbol. If BUFFER is nil or omitted, it defaults to the current buffer. If BUFFER already has a parser for LANGUAGE with TAG, return that parser, but if NO-REUSE is non-nil, always create a new parser.

TAG can be any symbol except t, and defaults to nil. Different parsers can have the same tag.

If that buffer is an indirect buffer, its base buffer is used instead. That is, indirect buffers use their base buffer's parsers. Lisp programs should widen as necessary should they want to use a parser in an indirect buffer.

Other relevant functions are documented in the treesit group.

View in manual

Shortdoc

;; treesit
(treesit-parser-create 'c)
    e.g. => #<treesit-parser for c>

Source Code

// Defined in /usr/src/emacs/src/treesit.c
{
  treesit_initialize ();

  CHECK_SYMBOL (language);
  CHECK_SYMBOL (tag);
  struct buffer *buf;
  Lisp_Object buf_orig;

  if (NILP (buffer))
    {
      buf = current_buffer;
      XSETBUFFER (buf_orig, current_buffer);
    }
  else
    {
      CHECK_BUFFER (buffer);
      buf = XBUFFER (buffer);
      buf_orig = buffer;
    }

  if (buf->base_buffer)
    buf = buf->base_buffer;

  if (EQ (tag, Qt))
    xsignal2(Qwrong_type_argument, list2(Qnot, Qt), Qt);

  treesit_check_buffer_size (buf);

  Lisp_Object remapped_lang = resolve_language_symbol (language);
  CHECK_SYMBOL (remapped_lang);

  /* See if we can reuse a parser.  */
  if (NILP (no_reuse))
    {
      Lisp_Object tail = BVAR (buf, ts_parser_list);
      FOR_EACH_TAIL (tail)
      {
	struct Lisp_TS_Parser *parser = XTS_PARSER (XCAR (tail));
	if (EQ (parser->tag, tag)
	    && EQ (parser->language_symbol, language)
	    && EQ (parser->buffer, buf_orig))
	  return XCAR (tail);
      }
    }

  /* Load language.  */
  Lisp_Object signal_symbol = Qnil;
  Lisp_Object signal_data = Qnil;
  TSParser *parser = ts_parser_new ();
  struct treesit_loaded_lang loaded_lang
    = treesit_load_language (remapped_lang, &signal_symbol, &signal_data);
  TSLanguage *lang = loaded_lang.lang;
  if (lang == NULL)
    xsignal (signal_symbol, signal_data);
  /* We check language version when loading a language, so this should
     always succeed.  */
  ts_parser_set_language (parser, lang);

  const bool lang_need_linecol_tracking
    = !NILP (Fmemq (remapped_lang,
		    Vtreesit_languages_require_line_column_tracking));

  /* Create parser.  Use the unmapped LANGUAGE symbol, so the nodes
     created by this parser (and the parser itself) identify themselves
     as the unmapped language.  This makes the grammar mapping
     completely transparent.  */
  Lisp_Object lisp_parser = make_treesit_parser (buf_orig,
						 parser, NULL,
						 language, tag,
						 lang_need_linecol_tracking);

  /* Enable line-column tracking if this language requires it.  */
  if (lang_need_linecol_tracking && !treesit_buf_tracks_linecol_p (buf))
    {
      /* We can use TREESIT_BOB_LINECOL for begv and zv since these
         cache doesn't need to be always in sync with BEGV and ZV.  */
      SET_BUF_TS_LINECOL_BEGV (buf, TREESIT_BOB_LINECOL);
      SET_BUF_TS_LINECOL_POINT (buf, TREESIT_BOB_LINECOL);
      SET_BUF_TS_LINECOL_ZV (buf, TREESIT_BOB_LINECOL);
    }

  /* Update parser-list.  */
  BVAR (buf, ts_parser_list) = Fcons (lisp_parser, BVAR (buf, ts_parser_list));

  return lisp_parser;
}