I am writing a Tree-Sitter grammar, I want to include escape sequences as child nodes within string literals, but I also want to avoid matching comments as extras within string literals.
The input "https://example.com"
is not parsed correctly because of the //
.
extras: $ => [$.comment],
rules: [
comment: $ => choice(
seq('//', /[^\n]*\n?/),
seq('/*', /([^\*]|\*[^\/])*/, '*/'),
),
escape: $ => /\\./,
// This one detects escape sequences, but fails on `//`
string: $ => seq('"', repeat(choice(/[^\"\\]/, $.escape)), '"'),
// This one doesn't detect escape sequences, but does not fail on `//`
string: $ => /"([^\"\\]|\\.)*"/,
],
I tried the token.immediate
modifier, but I did not manage to make it work (I don't really understand how is it supposed to be used). In the following example, the calls to token.immediate
have no effect.
string: $ => seq('"', optional($._string_tail), token.immediate('"')),
_string_tail: $ => seq(
choice(
token.immediate(/[^\"\\]/),
alias(token.immediate(/\\./), $.escape)
),
optional($._string_tail)
),
I also tried to put a lower precedence on comment rule, but it has no effect.