aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2025-02-27 03:05:26 -0800
committerYuan Fu2025-02-27 17:22:03 -0800
commit30e1508ef2d40e221736cea2c50c64941d7d2f0d (patch)
tree4a57810159f99c6329277fe71cfb6cec432ae420
parent32da093e524d5e28945557701f7c50d7c4a898cd (diff)
downloademacs-30e1508ef2d40e221736cea2c50c64941d7d2f0d.tar.gz
emacs-30e1508ef2d40e221736cea2c50c64941d7d2f0d.zip
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.
-rw-r--r--src/treesit.c69
-rw-r--r--src/treesit.h22
2 files changed, 91 insertions, 0 deletions
diff --git a/src/treesit.c b/src/treesit.c
index 62606d99749..16308193bf5 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1367,6 +1367,8 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
1367 lisp_parser->after_change_functions = Qnil; 1367 lisp_parser->after_change_functions = Qnil;
1368 lisp_parser->tag = tag; 1368 lisp_parser->tag = tag;
1369 lisp_parser->last_set_ranges = Qnil; 1369 lisp_parser->last_set_ranges = Qnil;
1370 lisp_parser->embed_level = Qnil;
1371 lisp_parser->parent_node = Qnil;
1370 lisp_parser->buffer = buffer; 1372 lisp_parser->buffer = buffer;
1371 lisp_parser->parser = parser; 1373 lisp_parser->parser = parser;
1372 lisp_parser->tree = tree; 1374 lisp_parser->tree = tree;
@@ -1818,6 +1820,69 @@ DEFUN ("treesit-parser-tag",
1818 return XTS_PARSER (parser)->tag; 1820 return XTS_PARSER (parser)->tag;
1819} 1821}
1820 1822
1823DEFUN ("treesit-parser-embed-level",
1824 Ftreesit_parser_embed_level, Streesit_parser_embed_level,
1825 1, 1, 0,
1826 doc: /* Return PARSER's embed level.
1827
1828The embed level can be either nil or a non-negative integer. A value of
1829nil means the parser isn't part of the embedded parser tree. The
1830primary parser has embed level 0, from it, each layer of embedded parser
1831has +1 embed level. */)
1832 (Lisp_Object parser)
1833{
1834 treesit_check_parser (parser);
1835 return XTS_PARSER (parser)->embed_level;
1836}
1837
1838/* TODO: Mention in manual, once the API stabilizes. */
1839DEFUN ("treesit-parser-set-embed-level",
1840 Ftreesit_parser_set_embed_level, Streesit_parser_set_embed_level,
1841 2, 2, 0,
1842 doc: /* Set the embed level for PARSER to LEVEL. */)
1843 (Lisp_Object parser, Lisp_Object level)
1844{
1845 treesit_check_parser (parser);
1846 if (!NILP (level))
1847 {
1848 CHECK_NUMBER (level);
1849 if (XFIXNUM (level) < 0)
1850 xsignal (Qargs_out_of_range, list1 (level));
1851 }
1852
1853 XTS_PARSER (parser)->embed_level = level;
1854 return level;
1855}
1856
1857DEFUN ("treesit-parser-parent-node",
1858 Ftreesit_parser_parent_node, Streesit_parser_parent_node,
1859 1, 1, 0,
1860 doc: /* Return PARSER's parent node, if one exists.
1861
1862Only embeded local parser can have parent node. When Emacs uses a node
1863in the host parser to create this local parser, that node is considered
1864the parent node of the local parser. */)
1865 (Lisp_Object parser)
1866{
1867 treesit_check_parser (parser);
1868 return XTS_PARSER (parser)->parent_node;
1869}
1870
1871DEFUN ("treesit-parser-set-parent-node",
1872 Ftreesit_parser_set_parent_node, Streesit_parser_set_parent_node,
1873 2, 2, 0,
1874 doc: /* Return PARSER's parent node to NODE. */)
1875 (Lisp_Object parser, Lisp_Object node)
1876{
1877 treesit_check_parser (parser);
1878 if (!NILP (node))
1879 CHECK_TS_NODE (node);
1880
1881 XTS_PARSER (parser)->parent_node = node;
1882 return node;
1883}
1884
1885
1821/* Return true if PARSER is not deleted and its buffer is live. */ 1886/* Return true if PARSER is not deleted and its buffer is live. */
1822static bool 1887static bool
1823treesit_parser_live_p (Lisp_Object parser) 1888treesit_parser_live_p (Lisp_Object parser)
@@ -4538,6 +4603,10 @@ applies to LANGUAGE-A will be redirected to LANGUAGE-B instead. */);
4538 defsubr (&Streesit_parser_buffer); 4603 defsubr (&Streesit_parser_buffer);
4539 defsubr (&Streesit_parser_language); 4604 defsubr (&Streesit_parser_language);
4540 defsubr (&Streesit_parser_tag); 4605 defsubr (&Streesit_parser_tag);
4606 defsubr (&Streesit_parser_embed_level);
4607 defsubr (&Streesit_parser_set_embed_level);
4608 defsubr (&Streesit_parser_parent_node);
4609 defsubr (&Streesit_parser_set_parent_node);
4541 4610
4542 defsubr (&Streesit_parser_root_node); 4611 defsubr (&Streesit_parser_root_node);
4543 defsubr (&Streesit_parse_string); 4612 defsubr (&Streesit_parse_string);
diff --git a/src/treesit.h b/src/treesit.h
index 19dc28af246..d19a0e76216 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -63,6 +63,28 @@ struct Lisp_TS_Parser
63 but rather return DEFAULT_RANGE. (A single range where start_byte 63 but rather return DEFAULT_RANGE. (A single range where start_byte
64 = 0, end_byte = UINT32_MAX). */ 64 = 0, end_byte = UINT32_MAX). */
65 Lisp_Object last_set_ranges; 65 Lisp_Object last_set_ranges;
66 /* Parsers for embedded code blocks will have a non-zero embed level.
67 The primary parser has level 0, and each layer of embedded parser
68 gets +1 level. The embed level can be either a non-negative
69 integer or nil. Every parser created by treesit-parser-create
70 starts with a nil level. If the value is nil, that means the range
71 functions (treesit-update-ranges and friends) haven't touched this
72 parser yet, and this parser isn't part of the embed parser tree. */
73 Lisp_Object embed_level;
74 /* Some comments: Technically you could calculate embed_level by
75 following parent_node, but parent_node might be outdated so it's a
76 good idea to record embed_level separately. Embed_level and
77 parent_node could have been implemented as "parser properties" with
78 an obarray, but ultimately I think two explicit fields helps
79 documentation better and it's not clear to me that a property list
80 for a parser will be useful beyond this. And we can always convert
81 these to properties later, but not vice versa. */
82 /* When an embedded parser is created, it's usually based on a node in
83 the host parser. This field saves that node so it possible to
84 climb up and out of the embedded parser into the host parser. Note
85 that the range of the embedded parser doesn't have to match that of
86 the parent node. */
87 Lisp_Object parent_node;
66 /* The buffer associated with this parser. */ 88 /* The buffer associated with this parser. */
67 Lisp_Object buffer; 89 Lisp_Object buffer;
68 /* The pointer to the tree-sitter parser. Never NULL. */ 90 /* The pointer to the tree-sitter parser. Never NULL. */