首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使treesitter与classname匹配

使treesitter与classname匹配
EN

Stack Overflow用户
提问于 2020-02-10 16:39:05
回答 1查看 242关注 0票数 1

我正在使用Treesitter来解析Clojure代码。具体地说,我想区分符号、类名和Java Interop

这是我的语法:

代码语言:javascript
复制
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*/
    }
})

我期待着

代码语言:javascript
复制
foo
java.lang.String
.toUpperCase
java.awt.Point.

要解析到

代码语言:javascript
复制
(program (
    (symbol)
    (classname)
    (member_access)
    (new_class (classname)))

但是Treesitter一直在使用(new_class (classname)) (classname),而不是Java.lang.String(classname)。我想我需要某种贪婪的匹配,并且已经在不同的地方尝试了prec.right(),但都没有效果。我遗漏了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-11 18:14:16

我是一个新手,所以请在处理以下内容时考虑到这一点:)

extras包含此语法的空格。IIUC,这意味着如果一个人没有在seq周围适当地使用token,树-sitter将试图解释seq中的项之间可能出现空格的情况。

例如,对于:

代码语言:javascript
复制
seq($._dot, $._class_chars)

tree将尝试将由空格分隔的有效$._dot$._class_chars视为有效。但IIUC在Clojure中不一定等同于它们不用空格分隔的情况。

但是,似乎不能在所有地方使用token,所以仅仅使用上面提到的seq的用法可能行不通。我的猜测是,粗略地说,如果seq的所有参数都是标记,那么可以在seq中使用token

下面是一个处理所提供的4个测试用例的示例。尽管事物被精确地解析为不同的东西,人们仍然可以做出适当的区分,AFAICT。

代码语言:javascript
复制
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语法的同名内容。)

(顺便说一句,ATM似乎在repository存储库中回答了有关tree-sitter的问题。有一些问题提到了其他地方讨论的可能性,但我还没有看到任何结果。您可能会在那里得到更好的答案。)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60146715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档