Match anything except if a negative rule matches

115 Views Asked by At

I have a rule that matches bc. When I encounter that in a string, I don't want to parse that string, otherwise parse anything else.

% Prolog

bc(B, C) --> [B, C], {
  B = "b",
  C = "c"
}.

not_bc(O) --> [O], % ?! bc(O, C).

% ?- phrase(not_bc(O), "bcdefg").
% false.
% ?- phrase(not_bc(O), "abcdefg").
% O = "a".
% ?- phrase(not_bc(O), "wxcybgz")
% O = "w".
% ?- phrase(not_bc(O), "wxybgz") 
% O = "w".

Simplified version of my problem, hopefully solutions are isomorphic.

Similar to this question: Translation to DCG Semicontext not working - follow on

2

There are 2 best solutions below

2
brebs On BEST ANSWER

An alternative:

process_bc(_) --> "bc", !, { fail }.
process_bc(C) --> [C].

This differs from my other solution in accepting:

?- time(phrase(process_bc(C), `b`, _)).
% 8 inferences, 0.000 CPU in 0.000 seconds (83% CPU, 387053 Lips)
C = 98.
0
brebs On

In swi-prolog:

process_text(C1) --> [C1, C2], { dif([C1, C2], `bc`) }.

Results:

?- time(phrase(process_text(C), `bca`, _)).
% 11 inferences, 0.000 CPU in 0.000 seconds (79% CPU, 376790 Lips)
false.

?- time(phrase(process_text(C), `bd`, _)).
% 10 inferences, 0.000 CPU in 0.000 seconds (80% CPU, 353819 Lips)
C = 98.

?- time(phrase(process_text(C), `zbcagri4gj40w9tu4tu34ty3ty3478t348t`, _)).
% 10 inferences, 0.000 CPU in 0.000 seconds (80% CPU, 372717 Lips)
C = 122.

A single character, or no characters, are both presumably meant to be failures.

This is nicely efficient, only having to check the first 2 characters.