1

有没有一种方法可以反向引用 parslet 中的前一个字符串,类似于\1典型正则表达式中的功能?

我想提取块中的字符,例如:

Marker SomeName
 some random text, numbers123
 and symbols !#%
SomeName  

其中“Marker”是一个已知的字符串,但“SomeName”是先验未知的,所以我相信我需要类似的东西:

rule(:name) { ( match('\w') >> match('\w\d') ).repeat(1) } 
rule(:text_within_the_block) {
 str('Marker') >>  name >> any.repeat.as(:text_block) >> backreference_to_name 
}  

我不知道如何使用 Parslet 和/或 Ruby 语言编写 backreference_to_name 规则

4

2 回答 2

3

来自http://kschiess.github.io/parslet/parser.html

捕获输入

有时解析器需要匹配已经匹配的东西。以 Ruby heredocs 为例:

  str = <-HERE
    This is part of the heredoc.
  HERE

匹配此类文档的关键是先捕获部分输入,然后根据捕获的部分构造解析器的其余部分。这是它最简单的形式:

  match['ab'].capture(:capt) >>               # create the capture
    dynamic { |s,c| str(c.captures[:capt]) }  # and match using the capture

这里的关键是该dynamic块返回一个惰性解析器。它仅在使用时进行评估,并在执行时将其传递给当前上下文以引用。

-- 更新:添加一个工作示例 --

所以对于你的例子:

require 'parslet'    
require 'parslet/convenience'

class Mini < Parslet::Parser
    rule(:name) { match("[a-zA-Z]") >> match('\\w').repeat }
    rule(:text_within_the_block) {  
         str('Marker ') >>  
         name.capture(:namez).as(:name) >> 
         str(" ") >> 
         dynamic { |_,scope| 
            (str(scope.captures[:namez]).absent? >> any).repeat 
         }.as(:text_block) >> 
         dynamic { |src,scope| str(scope.captures[:namez])  } 
     }

    root (:text_within_the_block)
end
puts Mini.new.parse_with_debug("Marker BOB some text BOB") .inspect 
 #=> {:name=>"BOB"@7, :text_block=>"some text "@11}

这需要进行一些更改。

  • 我更改了 rule(:name) 以匹配单个单词并添加了 astr(" ")以检测该单词已结束。(注意:\w 是 [A-Za-z0-9_] 的缩写,因此它包含数字)
  • 我将“任何”匹配更改为以文本不是:name文本为条件。(否则它会消耗“BOB”然后无法匹配,即它是贪婪的!)
于 2014-02-11T02:26:41.123 回答
0

我并不完全想支持 stackoverflow,但你似乎是一个 parslet 用户,这里是:尝试在邮件列表中询问一个真正好的答案。(http://dir.gmane.org/gmane.comp.lang.ruby.parslet

您在这里所说的反向引用在 parslet 中称为“捕获”。请参阅 parslets 源代码树中的示例“capture.rb”。

于 2014-01-10T10:07:50.057 回答