1

我目前正在使用 Ruby 编写一个 Ruby 解析器,更准确地说是 Parslet,因为我认为它比 Treetop 或 Citrus 更容易使用。我使用官方规范创建我的规则,但是有些语句我不能写,因为它们“排除”了一些语法,我不知道该怎么做......好吧,这是一个让你理解的例子。 ..

这是一个基本规则:

foo::=
any-character+ BUT NOT (foo* escape_character barbar*)
# Knowing that (foo* escape_character barbar*) is included in any-character

我怎么能用 Parslet 翻译呢?也许缺席?/现在?东西 ?

非常感谢,希望有大神给点意见。。。。

祝你今天过得愉快!

编辑:我试过你说的,所以这是我使用 parslet 翻译成 Ruby 语言:

  rule(:line_comment){(source_character.repeat >> line_terminator >> source_character.repeat).absent? >> source_character.repeat(1)}

但是,它似乎不起作用(括号中的序列)。我做了一些测试,得出的结论是我的括号中写的内容是错误的。

这是一个非常简单的示例,让我们考虑以下规则:

# Parslet rules
rule(:source_character) {any}
rule(:line_terminator){ str("\n") >> str("\r").maybe }  

rule(:not){source_character.repeat >> line_terminator }
# Which looks like what I try to "detect" up there

我用这段代码这些规则:

# Code to test : 
code = "test
"

但我明白了:

无法匹配第 2 行字符 1 处的序列 (SOURCE_CHARACTER{0, } LINE_TERMINATOR)。-- Failed to match sequence (SOURCE_CHARACTER{0, } LINE_TERMINATOR) at line 2 char 1.无法匹配第 2 行字符 1 处的序列 (''''?)。`- 第 2 行字符 1 处的输入过早结束。无

如果这个序列不起作用,我的“完整”规则将永远不会起作用......如果有人有想法,那就太好了。

谢谢 !

4

2 回答 2

5

你可以这样做:

rule(:word) { match['^")(\\s'].repeat(1) } # normal word
rule(:op) { str('AND') | str('OR') | str('NOT') }
rule(:keyword) { str('all:') | str('any:') }
rule(:searchterm) { keyword.absent? >> op.absent? >>  word }

在这种情况下,absent?会进行前瞻以确保下一个标记不是关键字;如果不是,则检查以确保它不是操作员;如果没有,最后看看它是否有效word

一个等效的规则是:

rule(:searchterm) { (keyword | op).absent? >> word }
于 2011-11-22T14:20:44.830 回答
5

Parslet 匹配本质上是贪婪的。这意味着当你重复类似的事情时

foo.repeat

parslet 将匹配 foo 直到失败。如果 foo 是

rule(:foo) { any }

您将走上失败的道路,因为 any.repeat 总是匹配整个文档的其余部分!

您正在寻找的是类似于示例/string_parser.rb(parslet 源树)中的字符串匹配器:

rule :string do
  str('"') >> 
  (
    (str('\\') >> any) |
    (str('"').absent? >> any)
  ).repeat.as(:string) >> 
  str('"')
end

这说的是:“匹配”,然后匹配一个反斜杠后跟任何字符,或者匹配任何其他字符,只要它不是终止的“。”

所以.缺席?确实是一种从以下匹配中排除事物的方法:

str('foo').absent? >> (str('foo') | str('bar'))

只会匹配'bar'。如果您理解这一点,我认为您将能够解决您的困难。尽管这些不会是您通往 Ruby 解析器的最后一步……

于 2011-11-23T14:19:45.643 回答