欧芹字直到分隔符存在

时间:2014-04-17 05:22:35

标签: ruby parslet

我刚开始使用ruby和parslet,所以这对其他人来说可能是显而易见的(希望如此)。

我想要将所有单词提取到分隔符(^)而不消耗它

以下规则适用(但使用分隔符),结果为{:wrd=>"otherthings"@0, :delim=>"^"@11}

require 'parslet'    
class Mini < Parslet::Parser
      rule(:word) { match('[a-zA-Z]').repeat}
      rule(:delimeter) { str('^') }
      rule(:othercontent) { word.as(:wrd) >> delimeter.as(:delim) }
      root(:othercontent)
end
puts Mini.new.parse("otherthings^")

我试图使用&#39; present?&#39;,

require 'parslet' 
class Mini < Parslet::Parser
  rule(:word) { match('[a-zA-Z]').repeat}
  rule(:delimeter) { str('^') }
  rule(:othercontent) { word.as(:wrd) >> delimeter.present? }
  root(:othercontent)
end
puts Mini.new.parse("otherthings^")

但这会引发异常:

Failed to match sequence (wrd:WORD &DELIMETER) at line 1 char 12. (Parslet::ParseFailed)

稍后我会想要检查分隔符右侧的单词以构建更复杂的语法,这就是我不想使用分隔符的原因。

我正在使用parslet 1.5.0。

感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

TL; DR; 如果你关心“^”之前的内容,你应该首先解析它。

---更长的答案---

解析器将始终使用所有文本。如果它不能消耗所有内容,那么语法就不能完整地描述文档。而不是将其视为在文本上“分裂”的东西......而是将其视为消耗文本流的聪明状态机。

所以...因为你的完整语法需要消耗所有文档...在开发你的解析器时,你不能让它解析一些部分而剩下的部分。您希望它将您的文档转换为树,以便您可以将其操作到最终。

如果你真的想在分隔符之前只使用所有文本,那么你可以做这样的事情......

说我打算解析'^'分开的事情列表。

我可以遵守以下规则

rule(:thing) { (str("^").absent? >> any).repeat(1) }  # anything that's not a ^
rule(:list)  { thing >> ( str("^") >> thing).repeat(0) } #^ separated list of things

这将如下工作

parse("thing1^thing2") #=> "thing1^thing2"
parse("thing1") #=> "thing1"
parse("thing1^") #=> ERROR ... nothing after the ^ there should be a 'thing'

这意味着list将匹配未结束或以'^'开头的字符串。为了有用,我需要使用“as”关键字

来提取值
rule(:thing) { (str("^").absent? >> any).repeat(1).as(:thing) }
rule(:list)  { thing >> ( str("^") >> thing).repeat(0) }

现在当list匹配一个字符串时,我得到了一系列“事物”的哈希值。

parse("thing1^thing2") #=> [ {:thing=>"thing1"@0} , {:thing=>"thing2"@7} ] 

实际上,你可能会关心“事物”是什么......不只是有什么东西会去那里。

在这种情况下......你应该首先定义这些规则...因为你不想使用解析器拆分“^”然后重新解析字符串以计算出它们的构成。

例如:

parse("6 + 4 ^ 2") 
 # => [ {:thing=>"6 + 4 "@0}, {:thing=>" 2"@7} ]

我可能想忽略“事物”周围的white_space,我可能想分别处理6 +和4。当我这样做时,我将不得不扔掉我所有“不是'^'”的规则。