diff --git a/spec/textquery_spec.rb b/spec/textquery_spec.rb index 6a7ea37..7cef6f3 100644 --- a/spec/textquery_spec.rb +++ b/spec/textquery_spec.rb @@ -69,5 +69,17 @@ def parse(input) parse("a AND b OR c").eval("c").should be_false parse("a AND b OR c").eval("b").should be_false end - + + it "should accept logical NOT" do + %w[- NOT].each do |operator| + parse("#{operator} a").eval("a").should be_false + parse("#{operator} #{operator} a").eval("a").should be_true + + parse("#{operator} a OR a").eval("a").should be_true + parse("a OR #{operator} a").eval("a").should be_true + + parse("b AND #{operator} a").eval("b").should be_true + parse("b AND #{operator} a").eval("a").should be_false + end + end end diff --git a/textquery.treetop b/textquery.treetop index a071357..f966ae7 100644 --- a/textquery.treetop +++ b/textquery.treetop @@ -27,6 +27,14 @@ grammar TextQuery } end + rule unary + ('-' / 'NOT') { + def eval(a) + not a + end + } + end + rule space [\s]* end @@ -44,6 +52,12 @@ grammar TextQuery end rule value + operator:unary space value { + def eval(text) + operator.eval(value.eval(text)) + end + } + / word end