3

Prolog プログラマーは通常、正規表現の代わりに DCG を使用して文字列内のパターンを照合することを理解しています。Perlでは、次のように書くかもしれません

if ( '... accd' =~ /a+b*c{2,4}d$/ ) {
    say "matched";
}

Prolog で同じパターンをどのように照合しますか?

4

1 に答える 1

1

この回答を拡張しました

:- 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 の文字列は文字コードのリストです)

于 2012-12-13T19:58:56.557 に答える