你怎么能要求一个未确定的字符在 Ruby Treetop 中连续重复一定次数?

How can you require an undetermined character to be repeated consecutively a certain number of times in Ruby Treetop?

我想创建一个规则,要求非数字、非字母字符连续重复三次。规则看起来像这样:

# Note, this code does not do what I want! 

grammar ThreeCharacters

  rule threeConsecutiveCharacters
    (![a-zA-Z0-9] .) 3..3
  end

end

有什么办法可以要求检测到的第一个字符重复3次?

之前有一个关于检测缩进数的类似问题:PEG for Python style indentation

首先初始化缩进堆栈的解决方案:

&{|s| @indents = [-1] }

然后保存当前行的缩进:

&{|s|
  level = s[0].indentation.text_value.length
  @indents << level
  true
}

每当新行开始时,它都会像这样查看缩进:

!{|s|
  # Peek at the following indentation:
  save = index; i = _nt_indentation; index = save
  # We're closing if the indentation is less or the same as our enclosing block's:
  closing = i.text_value.length <= @indents.last
}

如果缩进较大,它会将新的缩进级别添加到堆栈中。

我可以为我的问题创建类似的东西,但这似乎是一种非常乏味的解决方法。 还有其他方法可以创建我的规则吗?

是的,你可以在树顶上这样做。由于 Packrat 解析的工作方式,PEG 通常不可能实现这种事情;它很贪婪,但您需要使用解析早期的语义信息来限制它的贪婪。只是在 Treetop 中添加了语义谓词 (&{...}} 才使之成为可能。所以,是的,这很乏味。您可能会考虑改用 Rattler,因为除了 Treetop 中可用的功能之外,它还具有大量功能。我不能提供建议(作为 Treetop 的维护者,但不是 Rattler 的用户)但我对它的功能集印象深刻,我认为它会更好地处理这种情况。

如果您继续使用 Treetop,请记住每个语义谓词都应该 return 一个指示成功或失败的布尔值。这在上面 @indents 的初始化中并不明确。