Prolog プログラマーは通常、正規表現の代わりに DCG を使用して文字列内のパターンを照合することを理解しています。Perlでは、次のように書くかもしれません
if ( '... accd' =~ /a+b*c{2,4}d$/ ) {
say "matched";
}
Prolog で同じパターンをどのように照合しますか?
この回答を拡張しました
:- op(100, xf, *).
:- op(100, xf, +).
rexp(C) --> [C].
rexp([T|Ts]) --> rexp(T), rexp(Ts).
rexp([]) --> [].
rexp(eps) --> [].
rexp(_*) --> [].
rexp(R*) --> rexp(R), rexp(R*).
rexp(R+) --> rexp(R), rexp(R*).
rexp((R1|R2)) --> ( rexp(R1) ; rexp(R2) ).
rexp(range(R,N,M)) -->
{between(N,M,L),
length(D,L),
maplist(copy_term(R),D)
}, rexp(D).
次に、正規表現の一致が
?- phrase(rexp([a+, b*, range(c,2,4), d]), [a,c,c,d]),
writeln(matched).
この方法では、単一の文字ではなくアトムと一致することに注意してください。
false のコメントの後に編集します。最初の節は読むべきだと思います
rexp(C) --> {atomic(C)}, [C].
たとえば避けるために
?- phrase(rexp([a+]), [a+]).
true ;
実際、修正後、期待される結果が得られます。
?- phrase(rexp([a+]), [a+]).
false.
編集済み
正規表現を解釈する代わりに、パターンを「ハードコード」することができます (はるかに簡単です)。
% I prefer the equivalent clause below
% p1 --> "a", p1 ; "a", p2.
p1 --> "a", (p1 ; p2).
p2 --> "b", p2 ; p3.
p3 --> ("cc" ; "ccc" ; "cccc"), "d".
それから
?- phrase(p1, "accd").
true
ここでは、単一の文字に一致します (Prolog の文字列は文字コードのリストです)