Query Syntax
A query consists of one or more patterns, where each pattern is an S-expression that matches a certain set of
nodes in a syntax tree. The expression to match a given node consists of a pair of parentheses containing two things: the
node's type, and optionally, a series of other S-expressions that match the node's children. For example, this pattern would
match any binary_expression
node whose children are both number_literal
nodes:
(binary_expression (number_literal) (number_literal))
Children can also be omitted. For example, this would match any binary_expression
where at least one of child is a
string_literal
node:
(binary_expression (string_literal))
Fields
In general, it's a good idea to make patterns more specific by specifying field names associated with
child nodes. You do this by prefixing a child pattern with a field name followed by a colon. For example, this pattern would
match an assignment_expression
node where the left
child is a member_expression
whose object
is a call_expression
.
(assignment_expression
left: (member_expression
object: (call_expression)))
Negated Fields
You can also constrain a pattern so that it only matches nodes that lack a certain field. To do this, add a field name
prefixed by a !
within the parent pattern. For example, this pattern would match a class declaration with no type parameters:
(class_declaration
name: (identifier) @class_name
!type_parameters)
Anonymous Nodes
The parenthesized syntax for writing nodes only applies to named nodes. To match specific anonymous
nodes, you write their name between double quotes. For example, this pattern would match any binary_expression
where the
operator is !=
and the right side is null
:
(binary_expression
operator: "!="
right: (null))
Special Nodes
The Wildcard Node
A wildcard node is represented with an underscore (_
), it matches any node.
This is similar to .
in regular expressions.
There are two types, (_)
will match any named node,
and _
will match any named or anonymous node.
For example, this pattern would match any node inside a call:
(call (_) @call.inner)
The ERROR
Node
When the parser encounters text it does not recognize, it represents this node
as (ERROR)
in the syntax tree. These error nodes can be queried just like
normal nodes:
(ERROR) @error-node
The MISSING
Node
If the parser is able to recover from erroneous text by inserting a missing token and then reducing, it will insert that
missing node in the final tree so long as that tree has the lowest error cost. These missing nodes appear as seemingly normal
nodes in the tree, but they are zero tokens wide, and are internally represented as a property of the actual terminal node
that was inserted, instead of being its own kind of node, like the ERROR
node. These special missing nodes can be queried
using (MISSING)
:
(MISSING) @missing-node
This is useful when attempting to detect all syntax errors in a given parse tree, since these missing node are not captured
by (ERROR)
queries. Specific missing node types can also be queried:
(MISSING identifier) @missing-identifier
(MISSING ";") @missing-semicolon