【问题标题】:What does the regex (?!\G) do in language grammars正则表达式 (?!\G) 在语言语法中的作用
【发布时间】:2016-04-13 06:22:20
【问题描述】:

我经常在语言语法中看到这个正则表达式,它允许编辑器突出显示语法。

我知道正则表达式试图传达什么:

(?!\G) Negative Lookahead - Assert that it is impossible to match the regex below
\G assert position at the end of the previous match or the start of the string for the first match

这是引起我注意的sn-p:

控制台

# console.log(arg1, "arg2", [...])
'begin': '\\bconsole\\b'
'beginCaptures':
  '0':
    'name': 'entity.name.type.object.console.js'
'end': '(?!\\G)'
'patterns': [
  {
    'begin': '\\s*(\\.)\\s*(assert|clear|debug|error|info|log|profile|profileEnd|time|timeEnd|warn)\\s*(?=\\()'
    'beginCaptures':
      '1':
        'name': 'meta.delimiter.method.period.js'
      '2':
        'name': 'support.function.console.js'
    'end': '(?<=\\))'
    'name': 'meta.method-call.js'
    'patterns': [
      {
        'include': '#arguments'
      }
    ]
  }
]

上面的sn-p来自atom/language-javascript包。

根据我通过浏览各种 text-mate 论坛了解到的情况,对于突出显示,编辑器将从 begin 开始,一直到 end 正则表达式。在这里,它首先匹配 console 关键字,然后继续直到它匹配 end 正则表达式,我无法理解,比如它会在哪里停止?

谁能解释一下?

【问题讨论】:

  • 我知道前瞻。我在\G 的上下文中问这个问题,特别是语言语法如何解释这个
  • \G - 字符串位置的开始或上一个成功匹配的结束。 (?!\G) - 不是可以与\G匹配的同一位置。
  • @WiktorStribiżew 我的问题更关心这将如何影响语法高亮编辑器的最终匹配
  • 您对问题进行了标记和构建,听起来确实像是一个骗局。请编辑它,标记atom正则表达式 (?!\G) 有什么作用? 标题使它成为 What does the regex mean 的欺骗。
  • @WiktorStribiżew 我已经编辑了问题的标题和标签

标签: regex grammar atom-editor


【解决方案1】:

看到一些Language Grammars reference first:

规则可以通过两种方式匹配文档。它可以提供一个或两个正则表达式。与上面第一条规则(第 6-8 行)中的 match 键一样,与该正则表达式匹配的所有内容都将获得该规则指定的名称。 ... 另一种匹配类型是第二条规则使用的匹配类型(第 9-17 行)。这里使用beginend 键给出了两个正则表达式。规则的名称将从开始模式匹配的位置分配到结束模式匹配的位置(包括两个匹配项)。如果end 模式不匹配,则使用文档的结尾。

在后一种形式中,规则可以具有与开始匹配和结束匹配之间的部分匹配的子规则。

请注意,正则表达式一次只匹配文档的单行。这意味着不可能使用匹配多行的模式

beginend — 这些键允许匹配跨越多行并且必须与match 键互斥。每个都是正则表达式模式。 begin 是开始块的模式,end 是结束块的模式

您提供的规则匹配 console.log 等文本并突出显示 3 个不同的部分:console.log

'begin': '\\bconsole\\b'
'beginCaptures':
  '0':
    'name': 'entity.name.type.object.console.js'
'end': '(?!\\G)'

这里,将console作为一个完整的单词进行匹配,整个匹配(因为第0组是整个匹配)命名为entity.name.type.object.console.js,然后正则表达式匹配直到(?!\G)的任何字符,匹配任何位置这不是最后一次成功匹配的结尾,也不是字符串的开头。这对于让其他嵌套规则起作用是必要的,即那些匹配 '\\s*(\\.)\\s*(assert|clear|debug|error|info|log|profile|profileEnd|time|timeEnd|warn)\\s*(?=\\()' 模式的规则。否则,该块将在之前完成,并且将跳过方法名称的匹配。

【讨论】:

  • 所以如果我只需要匹配没有任何嵌套规则的console,我就必须为此创建一个单独的规则,对吧?
  • 你可以,可能有一个否定的前瞻,将匹配限制为console,后面没有.(比如\\bconsole\\b(?!\\.)),或者你可以添加整个子规则否定前瞻的表达式。
  • 还有一个疑问!(?!\G) 所指的最后一次成功匹配是否总是指console 之后的位置。我的意思是,我仍然不明白它是如何知道的,此时停止匹配。假设嵌套规则永远不会匹配,那么它永远不会停止吗?
  • 是的,在整个单词console 之后(即文件末尾(=新类型)或紧跟非单词字符)。并且由于console被匹配,并且成功匹配的结束正好在e之后,所以(?!\G)不匹配,当前的console应该被高亮显示。然后,当您输入. 时,(?!\G) 应该在点之后匹配。
  • 是的,这是因为您添加了不在替代列表中的.bind。尝试用'begin': '\\s*(\\.)\\s*((?:assert|clear|debug|error|info|log|profile|profileEnd|time|timeEnd|warn)(?:\\.bind)?)\\s*(?=\\()' 替换'begin': '\\s*(\\.)\\s*(assert|clear|debug|error|info|log|profile|profileEnd|time|timeEnd|warn)\\s*(?=\\()'评论已更新
猜你喜欢
  • 1970-01-01
  • 2013-11-18
  • 1970-01-01
  • 2016-12-14
  • 2019-07-26
  • 2013-04-27
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
相关资源
最近更新 更多