Невозможно закодировать приоритет правила блока над правилом оператора в tree-sitter

Я пытаюсь закодировать простую грамматику, которая охватывает как простые операторы, так и операторы, заключенные в блок. Для блока есть специальное ключевое слово. Я указал приоритет правила блока выше нуля, но tree-sitter по-прежнему не соответствует ему. Даже он сообщает об ошибке, т.е. другие правила не совпадают. Но, тем не менее, он не хочет совпадать с блоком! Почему и как исправить?

Код:

      area = pi*r^2;

block {
    r=12;
}

tree-sitter соответствует всей последовательности block { r=12;как утверждение, несмотря на то, что фигурные скобки в утверждениях запрещены. Таким образом, он сообщает об ошибке, но не хочет соответствовать правилу блокировки, хотя оно применимо.

Грамматика:

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

    rules: {
        source_file: $ => seq(
            repeat(choice($.block, $.statement_with_semicolon)),
            optional($.statement_without_semicolon)
        ),

        block: $ => prec(1, seq(
            "block",
            "{",
            repeat( $.statement_with_semicolon ),
            optional( $.statement_without_semicolon),
            "}",
            optional(";")
        )),

        statement_without_semicolon: $ => $.token_chain,

        statement_with_semicolon: $ => seq(
            $.token_chain,
            ";"
        ),

        token_chain: $ => repeat1(
            $.token
        ),

        token: $ => choice(
            $.alphanumeric,
            $.punctuation
        ),

        alphanumeric: $ => /[a-zA-Zα-ωΑ-Ωа-яА-Я0-9]+/,

        punctuation: $ => /[^a-zA-Zα-ωΑ-Ωа-яА-Я0-9"{}\(\)\[\];]+/
    }
});

Выход:

      >tree-sitter parse example-file
(source_file [0, 0] - [4, 1]
  (statement_with_semicolon [0, 0] - [0, 14]
    (token_chain [0, 0] - [0, 13]
      (token [0, 0] - [0, 4]
        (alphanumeric [0, 0] - [0, 4]))
      (token [0, 4] - [0, 7]
        (punctuation [0, 4] - [0, 7]))
      (token [0, 7] - [0, 9]
        (alphanumeric [0, 7] - [0, 9]))
      (token [0, 9] - [0, 10]
        (punctuation [0, 9] - [0, 10]))
      (token [0, 10] - [0, 11]
        (alphanumeric [0, 10] - [0, 11]))
      (token [0, 11] - [0, 12]
        (punctuation [0, 11] - [0, 12]))
      (token [0, 12] - [0, 13]
        (alphanumeric [0, 12] - [0, 13]))))
  (statement_with_semicolon [0, 14] - [3, 9]
    (token_chain [0, 14] - [3, 8]
      (token [0, 14] - [2, 0]
        (punctuation [0, 14] - [2, 0]))
      (token [2, 0] - [2, 5]
        (alphanumeric [2, 0] - [2, 5]))
      (token [2, 5] - [2, 6]
        (punctuation [2, 5] - [2, 6]))
      (ERROR [2, 6] - [2, 7])
      (token [2, 7] - [3, 4]
        (punctuation [2, 7] - [3, 4]))
      (token [3, 4] - [3, 5]
        (alphanumeric [3, 4] - [3, 5]))
      (token [3, 5] - [3, 6]
        (punctuation [3, 5] - [3, 6]))
      (token [3, 6] - [3, 8]
        (alphanumeric [3, 6] - [3, 8]))))
  (statement_without_semicolon [3, 9] - [4, 0]
    (token_chain [3, 9] - [4, 0]
      (token [3, 9] - [4, 0]
        (punctuation [3, 9] - [4, 0]))))
  (ERROR [4, 0] - [4, 1]))
example-file    0 ms    (ERROR [2, 6] - [2, 7])

1 ответ

Ваша проблема в том, что ваше регулярное выражение соответствует символам новой строки \n а также \r, который вы можете увидеть здесь:

        (statement_with_semicolon [0, 14] - [3, 9]
    (token_chain [0, 14] - [3, 8]
      (punctuation [0, 14] - [2, 0]))

Посмотрите, как он совпадает с концом нулевой строки и пустой первой строкой? К тому времени, когда парсер доберется до block он думает, что блок - это просто еще один токен в statement_with_semicolon соответствие alphanumeric. Вы можете решить эту немедленную проблему, изменив свой punctuation определение к:

      punctuation: $ => /[^a-zA-Zα-ωΑ-Ωа-яА-Я0-9"{}\(\)\[\];\n\r]+/

Однако, вероятно, это будет не последняя проблема такого типа, с которой вы столкнетесь, поэтому вы можете переписать свою грамматику, чтобы она была более точной в отношении знаков препинания, которые она принимает, и где. Например, определение набора допустимых операторов.

Это также ответ на ваш другой вопрос.

Другие вопросы по тегам