Невозможно закодировать приоритет правила блока над правилом оператора в 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]+/
Однако, вероятно, это будет не последняя проблема такого типа, с которой вы столкнетесь, поэтому вы можете переписать свою грамматику, чтобы она была более точной в отношении знаков препинания, которые она принимает, и где. Например, определение набора допустимых операторов.
Это также ответ на ваш другой вопрос.