сделать TreeSitre соответствовать классу - PullRequest
1 голос
/ 10 февраля 2020

Я использую Treesitter для анализа кода Clojure. В частности, я хотел бы различать guish между символами, именами классов и Java Interop .

Это моя грамматика:

module.exports = grammar({
    name: 'clojure',
    extras: $ => [/[\s,]/],
    rules: {
        program: $ => repeat($._anything),
        _anything: $ => choice($.symbol, $.classname, $.member_access, $.new_class),

        symbol: $ => $._symbol_chars,

        classname: $ => prec.left(3, seq($._symbol_chars, repeat1($._classname_part ))),
        _classname_part: $ => prec.right(3, seq($._dot, $._symbol_chars)),

        member_access: $ => seq($._dot, $._class_chars),
        new_class: $ => prec(2, seq( choice($.symbol, $.classname), $._dot)),

        _dot: $ => /\.{1}/,
        _symbol_chars: $ =>   /[a-zA-Z\*\+\!\-_\?][\w\*\+\!\-\?\':]*/,
        _class_chars: $ => /[a-zA-Z_]\w*/
    }
})

I ожидал, что

foo
java.lang.String
.toUpperCase
java.awt.Point.

будет проанализирован до

(program (
    (symbol)
    (classname)
    (member_access)
    (new_class (classname)))

Но Treesitter продолжает видеть (new_class (classname)) (classname) вместо (classname) для Java.lang.String. Я полагаю, что мне нужно какое-то жадное совпадение, и я пробовал prec.right() в разных местах безрезультатно. Чего мне не хватает?

1 Ответ

2 голосов
/ 11 февраля 2020

Я новичок ie, сидящий на деревьях, поэтому, пожалуйста, примите это во внимание при обработке следующего:)

extras содержит пробел для этой грамматики. IIU C, это означает, что, если не использовать token вокруг seq надлежащим образом, средство поиска деревьев попытается учесть случаи, когда между элементами в seq.

могут возникать пробелы. Например, для:

seq($._dot, $._class_chars)

сортировщик деревьев будет пытаться рассматривать как действительные $._dot и $._class_chars, разделенные пробелами. Но IIU C, который не обязательно эквивалентен в Clojure случаю, когда они не разделены пробелами.

Похоже, что token не может использоваться повсеместно, так что просто поместите его вокруг вышеупомянутых видов использование seq может не работать. Я предполагаю, что, примерно, если все аргументы seq являются токенами, token может использоваться вокруг seq.

Ниже приведен пример, который, по-видимому, обрабатывает 4 предоставленных тестовых примера. Хотя то, что анализируется, точно отличается, все же можно сделать соответствующие различия, AFAICT.

const JAVA_ID = /[a-zA-Z_]\w*/;

module.exports = grammar({

    name: 'clojure',

    extras: $ =>
        [/[\s,]/],

    rules: {
        program: $ =>
            repeat($._anything),

        _anything: $ =>
            choice($.symbol,
                   $.member_access,
                   $.new_class),

        symbol: $ =>
            choice($._symbol_chars,
                   $.scoped_identifier),

        // XXX: approximate, see: https://clojure.org/reader
        _symbol_chars: $ =>
            /[a-zA-Z\*\+\!\-_\?][\w\*\+\!\-\?\':]*/,

        // XXX: except $ can be used too for inner classes?
        scoped_identifier: $ =>
            token(seq(JAVA_ID,
                      repeat(seq('.', JAVA_ID)))),

        // e.g. .toUpperCase
        member_access: $ =>
            token(seq('.',
                      JAVA_ID,
                      repeat(seq('.', JAVA_ID)))),

        // e.g. java.lang.String.
        new_class: $ =>
            token(seq(JAVA_ID,
                      repeat(seq('.', JAVA_ID)),
                      '.')),

    }
});

function sep1 (rule, separator) {
    return seq(rule, repeat(seq(separator, rule)));
}

Обратите внимание, что версия tree-sitter-cli может иметь значение - я использовал 0.16.4. Когда я попробовал вашу грамматику, я не получил того же результата, что и вы.

(Бит scoped_identifier был несколько вдохновлен чем-то с таким же именем из грамматики tree-sitter- java. )

(С другой стороны, банкомат, похоже, что вопросы о дровосеке отправляются в репозиторий github дровосеков. Там были некоторые проблемы с упоминанием возможности других мест для обсуждения, но я еще ничего не видел. Вы можете получить лучшие ответы там.)

...