将小正则表达式转换为DCG

时间:2012-12-13 19:10:41

标签: prolog dcg

据我所知,Prolog程序员通常使用DCG而不是正则表达式来匹配字符串中的模式。在Perl中,可以写一个

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

如何在Prolog中匹配相同的模式?

1 个答案:

答案 0 :(得分:1)

我已经延长了this回答

:- 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).

请注意,这样我们匹配原子而不是单个字符。

错误'评论后

编辑,我认为第一个条款应该是

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中的字符串,它是字符代码列表)