【问题标题】:Matching nested constructs in TextMate / Sublime Text / Atom language grammars匹配 TextMate / Sublime Text / Atom 语言语法中的嵌套结构
【发布时间】:2014-12-13 15:03:30
【问题描述】:

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

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

问题是多行 cmets 可以嵌套:

  #| 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-`#`
    

因此整个表达式匹配一个不包含 |#

的字符串

更新:

在 TextMate 邮件列表上得到了 Allan Odgaard 的答复:

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

【问题讨论】:

    标签: sublimetext2 racket grammar textmate textmatebundles


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢您的调查。我很想用适当的解析器替换 TextMate 语法 - 唉,我首先查看 TextMate 语法的原因是因为 Github 放弃了对 Pygments 的支持(其中包括一个适当的 Racket 解析器)。那就是我被困在使用 TextMate 语法。现在,多行 cmets 不起作用并不是世界末日,但是如果无法匹配嵌套的 #| |# 正确的话就很难得到#; cmets 正确。一种 #;取消以下 s 表达式 - 在 Racket/Scheme/Lisp 中很常见。
    • 我会保留这个问题几天,如果没有人提出解决方案,我会接受你的回答。
    【解决方案2】:

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

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

    【讨论】:

    • 是的,只使用正则表达式是不可能的。 TextMate 语法允许正则表达式的“存储库”,可用于制定递归规则。
    【解决方案3】:

    您的想法是正确的,但看起来您的第二个模式也与“开始嵌套评论”序列 #| 匹配,这永远不会让您的递归 #multilinecomment 模式有机会启动。

    你所要做的就是用类似于

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

    【讨论】:

    • (  #(?!\|)  |  \|(?!#)  |  [^|#]  )+
    【解决方案4】:

    取出最后一个match。你不需要它。它与 textmate 自然会做的事情是多余的,即将所有附加文本匹配到 comment 范围内,直到结束标记出现,或者整个模式自行递归。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-17
      • 1970-01-01
      • 2019-01-29
      • 2013-01-17
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多