使用正则表达式的树梢语法问题

时间:2010-03-09 18:42:57

标签: ruby parsing regex-negation treetop

我有一个简单的语法设置:

grammar Test
   rule line
      (adjective / not_adjective)* {
         def content
             elements.map{|e| e.content }
         end
      }
   end
   rule adjective
      ("good" / "bad" / "excellent") {
          def content
              [:adjective, text_value]
          end
      }
   end
   rule not_adjective
      !adjective {
          def content
              [:not_adjective, text_value]
          end
      }
   end
end

让我们说我的输入是“这是一个好球。让我们用它”。这给出了一个错误,我现在没有提到,因为我想先了解错误的理论。 那么,我如何创建规则not_adjective,以便它匹配任何与规则形容词不匹配的东西?一般来说,如何编写“规则”(特别是在Treetop中)“不”与另一个命名规则匹配?

2 个答案:

答案 0 :(得分:1)

Treetop是一个parser generator,可以从名为Parsing Expression Grammars or PEG的特殊语法类生成解析器。
!expression的操作解释是,如果expression失败则成功,如果expression成功但消耗NO输入则失败。
要匹配规则expression不匹配的任何内容,请使用 dot 运算符(匹配任何内容)与否定运算符一起使用以避免某些“单词”:

( !expression . )* ie. "match anything BUT expression"

答案 1 :(得分:1)

以前的答案对于OP的问题是不正确的,因为它将匹配任何单个字符序列,直到任何形容词。因此,如果您看到字符串xyzgood,它将匹配xyz,并且以下规则将匹配" good"部分作为形容词。同样,OP的形容词规则将匹配"徽章"的前三个字符。作为形容词"坏",这不是他们想要的。

相反,形容词规则看起来应该是这样的:

rule adjective
  a:("good" / "bad" / "excellent") ![a-z] {
    def content
      [:adjective, a.text_value]
    end
  }
end

和not_adjective规则是这样的:

rule not_adjective
  !adjective w:([a-z]+) {
    def content
      [:not_adjective, w.text_value]
    end
  }
end

根据需要包括处理大写,连字符,撇号等。当然,您还需要处理空白区域。