Add 'and', 'named', and 'anonymous' predicate for tree-sitter
* doc/lispref/parsing.texi (User-defined Things): Mention the new predicate. * src/treesit.c (treesit_traverse_validate_predicate): Recognize named, anonymous, and and predicates. (treesit_traverse_match_predicate): Handle named, anonymous, and and predicates.
This commit is contained in:
parent
4687fff4f0
commit
f0e63558bd
2 changed files with 38 additions and 8 deletions
|
@ -1596,6 +1596,8 @@ the thing.
|
|||
|
||||
@var{pred} can also be recursively defined. It can be @w{@code{(or
|
||||
@var{pred}@dots{})}}, meaning that satisfying any one of the @var{pred}s
|
||||
qualifies the node as the thing. It can be @w{@code{(and
|
||||
@var{pred}@dots{})}}, meaning that satisfying all of the @var{pred}s
|
||||
qualifies the node as the thing. It can be @w{@code{(not @var{pred})}},
|
||||
meaning that not satisfying @var{pred} qualifies the node.
|
||||
|
||||
|
@ -1604,6 +1606,10 @@ list. For example, @w{@code{(or sexp sentence)}} defines something
|
|||
that's either a @code{sexp} thing or a @code{sentence} thing, as defined
|
||||
by some other rule in the alist.
|
||||
|
||||
There are two pre-defined predicates: @code{named} and @code{anonymous},
|
||||
that qualifies named and anonymous nodes, respectively. They can be
|
||||
combined with @code{and} to narrow down the match.
|
||||
|
||||
Here's an example @code{treesit-thing-settings} for C and C++:
|
||||
|
||||
@example
|
||||
|
@ -1662,7 +1668,6 @@ signals @code{treesit-invalid-predicate} error. If @var{ignore-missing}
|
|||
is @code{t}, this function doesn't signal the error when @var{thing} is
|
||||
undefined and just returns @code{nil}; but it still signals the error if
|
||||
@var{thing} is a malformed predicate.
|
||||
|
||||
@end defun
|
||||
|
||||
@defun treesit-thing-prev position thing
|
||||
|
@ -2179,8 +2184,6 @@ navigation commands that move, respectively, by sexps and sentences by
|
|||
defining variables such as @code{forward-sexp-function} and
|
||||
@code{forward-sentence-function}.
|
||||
@end itemize
|
||||
|
||||
@c TODO: Add treesit-thing-settings stuff once we finalize it.
|
||||
@end defun
|
||||
|
||||
For more information on these built-in tree-sitter features,
|
||||
|
|
|
@ -3623,6 +3623,9 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
|
|||
return true;
|
||||
else if (SYMBOLP (pred))
|
||||
{
|
||||
if (BASE_EQ (pred, Qnamed) || BASE_EQ (pred, Qanonymous))
|
||||
return true;
|
||||
|
||||
Lisp_Object definition = treesit_traverse_get_predicate (pred,
|
||||
language);
|
||||
if (NILP (definition))
|
||||
|
@ -3667,13 +3670,13 @@ treesit_traverse_validate_predicate (Lisp_Object pred,
|
|||
signal_data,
|
||||
recursion_level + 1);
|
||||
}
|
||||
else if (BASE_EQ (car, Qor))
|
||||
else if (BASE_EQ (car, Qor) || BASE_EQ (car, Qand))
|
||||
{
|
||||
if (!CONSP (cdr) || NILP (cdr))
|
||||
{
|
||||
*signal_data = list3 (Qtreesit_invalid_predicate,
|
||||
build_string ("`or' must have a list "
|
||||
"of patterns as "
|
||||
build_string ("`or' or `and' must have "
|
||||
"a list of patterns as "
|
||||
"arguments "),
|
||||
pred);
|
||||
return false;
|
||||
|
@ -3729,6 +3732,14 @@ treesit_traverse_match_predicate (TSTreeCursor *cursor, Lisp_Object pred,
|
|||
Lisp_Object lisp_node = make_treesit_node (parser, node);
|
||||
return !NILP (CALLN (Ffuncall, pred, lisp_node));
|
||||
}
|
||||
else if (SYMBOLP (pred) && BASE_EQ (pred, Qnamed))
|
||||
{
|
||||
return ts_node_is_named (node);
|
||||
}
|
||||
else if (SYMBOLP (pred) && BASE_EQ (pred, Qanonymous))
|
||||
{
|
||||
return !ts_node_is_named (node);
|
||||
}
|
||||
else if (SYMBOLP (pred))
|
||||
{
|
||||
Lisp_Object language = XTS_PARSER (parser)->language_symbol;
|
||||
|
@ -3755,6 +3766,16 @@ treesit_traverse_match_predicate (TSTreeCursor *cursor, Lisp_Object pred,
|
|||
}
|
||||
return false;
|
||||
}
|
||||
else if (BASE_EQ (car, Qand))
|
||||
{
|
||||
FOR_EACH_TAIL (cdr)
|
||||
{
|
||||
if (!treesit_traverse_match_predicate (cursor, XCAR (cdr),
|
||||
parser, named))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (STRINGP (car) && FUNCTIONP (cdr))
|
||||
{
|
||||
/* A bit of code duplication here, but should be fine. */
|
||||
|
@ -4297,6 +4318,7 @@ syms_of_treesit (void)
|
|||
DEFSYM (Qtreesit_compiled_query_p, "treesit-compiled-query-p");
|
||||
DEFSYM (Qtreesit_query_p, "treesit-query-p");
|
||||
DEFSYM (Qnamed, "named");
|
||||
DEFSYM (Qanonymous, "anonymous");
|
||||
DEFSYM (Qmissing, "missing");
|
||||
DEFSYM (Qextra, "extra");
|
||||
DEFSYM (Qoutdated, "outdated");
|
||||
|
@ -4338,6 +4360,7 @@ syms_of_treesit (void)
|
|||
DEFSYM (Qtreesit_thing_symbol, "treesit-thing-symbol");
|
||||
|
||||
DEFSYM (Qor, "or");
|
||||
DEFSYM (Qand, "and");
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
DEFSYM (Qtree_sitter, "tree-sitter");
|
||||
|
@ -4420,8 +4443,12 @@ cons (REGEXP . FN), which is a combination of a regexp and a predicate
|
|||
function, and the node has to match both to qualify as the thing.
|
||||
|
||||
PRED can also be recursively defined. It can be (or PRED...), meaning
|
||||
satisfying anyone of the inner PREDs qualifies the node; or (not
|
||||
PRED), meaning not satisfying the inner PRED qualifies the node.
|
||||
satisfying anyone of the inner PREDs qualifies the node; or (and
|
||||
PRED...) meaning satisfying all of the inner PREDs qualifies the node;
|
||||
or (not PRED), meaning not satisfying the inner PRED qualifies the node.
|
||||
|
||||
There are two pre-defined predicates, `named' and `anonymous`. They
|
||||
match named nodes and anonymous nodes, respectively.
|
||||
|
||||
Finally, PRED can refer to other THINGs defined in this list by using
|
||||
the symbol of that THING. For example, (or sexp sentence). */);
|
||||
|
|
Loading…
Add table
Reference in a new issue