来自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) 以匹配单个单词并添加了 a
str(" ")
以检测该单词已结束。(注意:\w 是 [A-Za-z0-9_] 的缩写,因此它包含数字)
- 我将“任何”匹配更改为以文本不是
:name
文本为条件。(否则它会消耗“BOB”然后无法匹配,即它是贪婪的!)