【问题标题】:Atom Language Definition using nested Regex patterns使用嵌套正则表达式模式的 Atom 语言定义
【发布时间】:2016-09-16 22:27:23
【问题描述】:

我实际上是在尝试在 Atom 中定义一个语法(效果出奇的好),并且在使用 Regex 3 天之后,感觉慢慢地发疯了。

问题是我现在离开了“简单”定义领域,所以我还需要比现在更好的正则表达式知识。

问题: 我想使用beginend 匹配4 个特定模式。 通过 Textmate 教程,我了解到行为应该是这样的:

begin: \w,end: \d 变为 \w(.*)\d

利用这些知识,我想匹配这四个表达式:

  1. foo( a(1) ):解析为“本身”嵌套的范围(与TextMate Language Example 中的qq-Strings 描述的方式相同。
  2. bar(1)('a'):解析为由字段(1) 访问的范围bar,因此是字段('a')bar 仅在至少存在第二个括号块的条件下才具有此范围。
  3. foo( bar(1)('a') ):(1)和(2)的混合物。 foo 被提取出来(1),bar 代表与(2)中描述的相同的东西。
  4. foo( bar(1)('a')('a') )('a'):最复杂的一个。 foo 表示可以使用第二个括号提取的元素,bar 表示可以通过相同机制提取并生成可以访问 foo 的值,而不会在运行时出现其他问题。

为了捕捉所有这些语句,我现在有两个正则表达式(CSON 语法如下):

'strange_accessors':
{
  'comment': 'tries to catch foo(a)(a)(a) constructs'
  'begin': '(?:' +
             '(?:(?<=\\))\\s*)'         + # closing parenthesis beforehand
             '|(?:[\\w%\\$\\?!#]*)'  + # character beforehand
           ')' +
           '\\s*'   +
           '(\\()'  +  # opening bracket
           '[^;]+?' +
           '(\\))'  +
           '\\s*(\\()'
  'end': '(\\))+?'

  'beginCaptures':
    '1':
      'name': 'punctuation.parens.begin.someLang'
    '2':
      'name': 'punctuation.parens.someLang'
    '3':
      'name': 'punctuation.parens.begin.someLang'
  'endCaptures':
    '0':
      'name': 'punctuation.parens.end.someLang'
}

所以,为了抓住括号,我用这个:

'surronding_parenthesis':
{
  'comment': 'describes a (nested) accessor using parenthesis'
  'begin':  '(?:[a-zA-Z_%\\$\\?!#][\\w%\\$\\?!#]*)'  + # character beforehand
           '(\\()'
  'end': '(?>(\\)))'

  'beginCaptures':
    '1':
      'name': 'punctuation.section.parens.begin.someLang'
  'endCaptures':
    '1':
      'name': 'punctuation.section.parens.end.someLang'
    '2':
      'name': 'banana.invalid.illegal.someLang'

  'patterns':[
    { 'include': '#strange_accessors'}
  ]

}

我在贪婪、不情愿和固执的行为以及原子团中摆弄我的方式,因为我认为这将是成功匹配的关键。

但我很困惑,不知道如何解决这个奇怪的嵌套问题。如果有人有兴趣并想试试我为什么需要这个:

这是Scilab 的语法。

【问题讨论】:

  • 递归在哪里?示例 Pcre (\(((?:[^()]++|(?1))*)\))
  • 刚刚尝试过,它匹配所有唯一括号中的模式。但我想要的是更像foo(foo(b))('a') 解析为foo(...)('a') 以及foo(b)

标签: regex coffeescript grammar atom-editor


【解决方案1】:

下面的这个正则表达式使用递归:

(?<=\s)\w+(\(((?:[^()]+|(?1))*?)\))(\('.*?'\))?

会匹配

  foo( a(1) )
  bar(1)('a')
  foo( bar(1)('a') )
  foo( bar(1)('a')('a') )('a')

你可以测试一下here on regex101
(Scilab 使用我在论坛上看到的 PCRE 正则表达式引擎)

请注意,它包含(?&lt;=\s) 的正向lookbehind,以确保在前导词之前有一个空格。
因为我怀疑你想匹配\b( a(1) )

这个正则表达式也会匹配它们,但没有递归。仅使用非捕获组:

(?<=\s)\w+\((?:.*?(?:\(.*?\))?)+\)(?:\('.*?'\))?

【讨论】:

  • 非常感谢 - 不完全是我想要的,但我可以自己扩展它。
  • 很高兴听到它有帮助。但是,如果您要添加一些有助于找到正确解决方案的示例源文本;)
  • 您是否真的在寻找 foo 和 bar?在这种情况下,只需将 \w+ 替换为 (?:foo|bar)
  • 不,它真的更像是“嵌套”提取。这就是我需要这个的原因:Scilab 有一些内置类型,他们称之为“struct”(我认为是结构化列表的缩写),您可以使用点 (,) 或括号来访问它们。显然,我无法区分结构或“正常”提取(如果使用括号),但对于一种情况:可以成功提取 struct。这意味着foo(a)(其中a 表示一个变量)只能是结构,如果a 是字符串类型,但foo(1)(a) 必须是语法定义的结构。当然,作为一个脚本编写者,你想嵌套它;)
  • 所以对于 Atom 语法,我的主要目标是捕捉两个最外面的括号的洞察力,然后使用相同的模式来捕捉里面的东西。快速测试看起来很有希望。
猜你喜欢
  • 2013-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2020-06-17
  • 2016-12-14
  • 2019-07-26
  • 1970-01-01
相关资源
最近更新 更多