在TextMate / Sublime Text / Atom语言语法中匹配嵌套构造

时间:2014-12-13 15:03:31

标签: sublimetext2 racket grammar textmate textmatebundles

在为Github编写语法时,语法高亮显示用Racket语言编写的程序,我偶然发现了一个问题。

在Racket中#|开始多行注释,|#结束它。

问题是多行注释可以嵌套:

  #| a comment  #| still a comment |# even 
                                      more comment |#

这是我的非工作尝试:

repository:
  multilinecomment: 
    begin:         \#\|
    end:           \|\#
    name:          comment
    contentName:   comment
    patterns:
    - include:     "#multilinecomment"
      name:        comment
    - match:       ([^\|]|\|(?=[^#]))*
      name:        comment

匹配模式的目的是:

  1. "#multilinecomment"  多行注释可以包含另一个多行注释。
  2. ([^\|]|\|(?=[^#]))* 子表达式的含义:

     [^\|]        any characters not an `|`
     \|(?=[^#])   an `|` followed by a non-`#`
    
  3. 因此整个表达式匹配不包含|#

    的字符串

    更新

    在TextMate邮件列表上找到了Allan Odgaard的答案:

    http://textmate.1073791.n5.nabble.com/TextMate-grammars-and-nested-multiline-comments-td28743.html

4 个答案:

答案 0 :(得分:2)

所以我在Sublime中测试了一堆具有多行注释(C / C ++,Java,HTML,PHP,JavaScript)的语言,并且没有一种语言语法支持多行注释中嵌入的多行注释 - 语法高亮显示comment范围以第一个“注释关闭”标记结束,而不是以对称标记结束。现在,这并不是说这是不可能的,因为BracketHighlighter插件非常适合匹配对称标签,括号和其他标记。但是,它是用Python编写的,并且使用自定义逻辑来匹配算法,这可能不是Oniguruma引擎中可用的,它可以为Sublime的语法高亮显示提供动力,而且显然也是Github's

基本上,根据您对问题的描述,您需要一个代码解析器来确保嵌套注释是合法的,这是您不能仅使用语法突出显示定义。如果您只是为Sublime编写这个,那么自定义插件可以解决这个问题,但我不太了解Github的Linguist语法高亮系统,如果您被允许这样做的话。我还不是一个正则表达式大师,但在我看来,纯粹通过正则表达式实现这一点是相当困难的,因为你需要以某种方式跟踪任意数量的内部对称“开放”和“关闭”在找到(并识别!)最后一个之前的标记。

对不起,除了我不确定这是否可能之外,我无法提供明确的答案,但这是我能想出的最好的,而不了解更多关于Sublime和Github的内部结构, (至少在Sublime的情况下)除非是开源的,否则不会发生。祝你好运!

答案 1 :(得分:1)

您有正确的想法,但看起来您的第二个模式也匹配“开始嵌套注释”序列#|,这将永远不会让您的递归#multilinecomment模式有机会启动。< / p>

您所要做的就是用类似于

的东西替换您的第二个模式
(#(?=[^|])|\|(?=[^#])|[^|#])+

答案 2 :(得分:1)

旧帖子,我没有评论的声誉,但强调不可能使用纯正则表达式检测任意嵌套的评论。直觉上,这是因为所有正则表达式都可以转换为有限状态机,并且跟踪嵌套深度需要(理论上)无限量的状态(状态的数量需要至少等于不同的可能嵌套深度,这里是无限的。)

在实践中,这个数字变得非常缓慢,所以如果你不想太麻烦,你可能会写一些允许嵌套到合理深度的东西。否则,你可能需要一个单独的阶段来解析并找到注释,告诉语法高亮显示器忽略它们。

答案 3 :(得分:0)

取出最后一个match。您不需要它。这对于文本伴侣自然会做的事情来说是多余的,那就是将所有其他文本匹配到comment范围中,直到结束标记出现,或者整个模式重新出现为止。