Tree-sitter, how to use a "catch all" rule correctly?

Viewed 95

I have a grammar like this:

terminator = '\n';

module.exports = grammar({
  name: 'sciname',

  rules: {
    source_file: ($) => repeat($._sci_name),

    _sci_name: ($) => seq($.uninomial, optional($.tail), terminator),

    _uninomial: ($) => /[A-Z][a-z]+/,

    uninomial: ($) => choice($._uninomial, seq($.genus, $.subgenus)),

    genus: ($) => $._uninomial,

    subgenus: ($) => seq('(', $._uninomial, ')'),

    tail: ($) => /.+/,
  },
});

tail rule suppose to catch anything that comes after uninomial. However I have trouble with this test:

=====================
Subgenus
=====================

Bubo (Bubo)

---------------------

(source_file (uninomial (genus) (subgenus)))

producing:

(source_file (uninomial) (tail))

instead of

(source_file (uninomial (genus) (subgenus)))

Changing precedence does not seem to influence this behavior. Is there a way to make a "catch-all" rule like tail to engage only if all other previous rules failed?

1 Answers
Related