Add tree-sitter-parser-embed-level and parent-node
Add parser properties embed-level and parent-node. They'll be help us implement arbitrarily nested embeded parser, and navigation across embedded and host parsers, respectively. * src/treesit.c: (Ftreesit_parser_embed_level): (Ftreesit_parser_set_embed_level): (Ftreesit_parser_parent_node): (Ftreesit_parser_set_parent_node): New functions.
This commit is contained in:
parent
32da093e52
commit
30e1508ef2
2 changed files with 91 additions and 0 deletions
|
@ -1367,6 +1367,8 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
|
|||
lisp_parser->after_change_functions = Qnil;
|
||||
lisp_parser->tag = tag;
|
||||
lisp_parser->last_set_ranges = Qnil;
|
||||
lisp_parser->embed_level = Qnil;
|
||||
lisp_parser->parent_node = Qnil;
|
||||
lisp_parser->buffer = buffer;
|
||||
lisp_parser->parser = parser;
|
||||
lisp_parser->tree = tree;
|
||||
|
@ -1818,6 +1820,69 @@ DEFUN ("treesit-parser-tag",
|
|||
return XTS_PARSER (parser)->tag;
|
||||
}
|
||||
|
||||
DEFUN ("treesit-parser-embed-level",
|
||||
Ftreesit_parser_embed_level, Streesit_parser_embed_level,
|
||||
1, 1, 0,
|
||||
doc: /* Return PARSER's embed level.
|
||||
|
||||
The embed level can be either nil or a non-negative integer. A value of
|
||||
nil means the parser isn't part of the embedded parser tree. The
|
||||
primary parser has embed level 0, from it, each layer of embedded parser
|
||||
has +1 embed level. */)
|
||||
(Lisp_Object parser)
|
||||
{
|
||||
treesit_check_parser (parser);
|
||||
return XTS_PARSER (parser)->embed_level;
|
||||
}
|
||||
|
||||
/* TODO: Mention in manual, once the API stabilizes. */
|
||||
DEFUN ("treesit-parser-set-embed-level",
|
||||
Ftreesit_parser_set_embed_level, Streesit_parser_set_embed_level,
|
||||
2, 2, 0,
|
||||
doc: /* Set the embed level for PARSER to LEVEL. */)
|
||||
(Lisp_Object parser, Lisp_Object level)
|
||||
{
|
||||
treesit_check_parser (parser);
|
||||
if (!NILP (level))
|
||||
{
|
||||
CHECK_NUMBER (level);
|
||||
if (XFIXNUM (level) < 0)
|
||||
xsignal (Qargs_out_of_range, list1 (level));
|
||||
}
|
||||
|
||||
XTS_PARSER (parser)->embed_level = level;
|
||||
return level;
|
||||
}
|
||||
|
||||
DEFUN ("treesit-parser-parent-node",
|
||||
Ftreesit_parser_parent_node, Streesit_parser_parent_node,
|
||||
1, 1, 0,
|
||||
doc: /* Return PARSER's parent node, if one exists.
|
||||
|
||||
Only embeded local parser can have parent node. When Emacs uses a node
|
||||
in the host parser to create this local parser, that node is considered
|
||||
the parent node of the local parser. */)
|
||||
(Lisp_Object parser)
|
||||
{
|
||||
treesit_check_parser (parser);
|
||||
return XTS_PARSER (parser)->parent_node;
|
||||
}
|
||||
|
||||
DEFUN ("treesit-parser-set-parent-node",
|
||||
Ftreesit_parser_set_parent_node, Streesit_parser_set_parent_node,
|
||||
2, 2, 0,
|
||||
doc: /* Return PARSER's parent node to NODE. */)
|
||||
(Lisp_Object parser, Lisp_Object node)
|
||||
{
|
||||
treesit_check_parser (parser);
|
||||
if (!NILP (node))
|
||||
CHECK_TS_NODE (node);
|
||||
|
||||
XTS_PARSER (parser)->parent_node = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if PARSER is not deleted and its buffer is live. */
|
||||
static bool
|
||||
treesit_parser_live_p (Lisp_Object parser)
|
||||
|
@ -4538,6 +4603,10 @@ applies to LANGUAGE-A will be redirected to LANGUAGE-B instead. */);
|
|||
defsubr (&Streesit_parser_buffer);
|
||||
defsubr (&Streesit_parser_language);
|
||||
defsubr (&Streesit_parser_tag);
|
||||
defsubr (&Streesit_parser_embed_level);
|
||||
defsubr (&Streesit_parser_set_embed_level);
|
||||
defsubr (&Streesit_parser_parent_node);
|
||||
defsubr (&Streesit_parser_set_parent_node);
|
||||
|
||||
defsubr (&Streesit_parser_root_node);
|
||||
defsubr (&Streesit_parse_string);
|
||||
|
|
|
@ -63,6 +63,28 @@ struct Lisp_TS_Parser
|
|||
but rather return DEFAULT_RANGE. (A single range where start_byte
|
||||
= 0, end_byte = UINT32_MAX). */
|
||||
Lisp_Object last_set_ranges;
|
||||
/* Parsers for embedded code blocks will have a non-zero embed level.
|
||||
The primary parser has level 0, and each layer of embedded parser
|
||||
gets +1 level. The embed level can be either a non-negative
|
||||
integer or nil. Every parser created by treesit-parser-create
|
||||
starts with a nil level. If the value is nil, that means the range
|
||||
functions (treesit-update-ranges and friends) haven't touched this
|
||||
parser yet, and this parser isn't part of the embed parser tree. */
|
||||
Lisp_Object embed_level;
|
||||
/* Some comments: Technically you could calculate embed_level by
|
||||
following parent_node, but parent_node might be outdated so it's a
|
||||
good idea to record embed_level separately. Embed_level and
|
||||
parent_node could have been implemented as "parser properties" with
|
||||
an obarray, but ultimately I think two explicit fields helps
|
||||
documentation better and it's not clear to me that a property list
|
||||
for a parser will be useful beyond this. And we can always convert
|
||||
these to properties later, but not vice versa. */
|
||||
/* When an embedded parser is created, it's usually based on a node in
|
||||
the host parser. This field saves that node so it possible to
|
||||
climb up and out of the embedded parser into the host parser. Note
|
||||
that the range of the embedded parser doesn't have to match that of
|
||||
the parent node. */
|
||||
Lisp_Object parent_node;
|
||||
/* The buffer associated with this parser. */
|
||||
Lisp_Object buffer;
|
||||
/* The pointer to the tree-sitter parser. Never NULL. */
|
||||
|
|
Loading…
Add table
Reference in a new issue