RegEx Parser用Prolog编写

时间:2011-01-22 07:18:02

标签: regex prolog dcg

我已经在这个家庭作业问题上一直撞到墙上几个小时了。我们必须用Prolog解析正则表达式。在大多数情况下,我使用的谓词,但是有一些正则表达式和字符串组合导致它们在SWI-Prolog中耗尽堆栈空间。这是一个包含两个正则表达式字符串组合的示例,一个有效,另一个无效:

star(star(char(a))), []
star(star(char(a))), [a]

第一个工作,第二个用完堆栈。

这是我正在使用的谓词:

re_match(epsilon, []).
re_match(char(Letter), [Letter]).
re_match(star(_), []).
re_match(seq(Rx1, Rx2), List) :- append(List1, List2, List),  re_match(Rx2, List2),  re_match(Rx1, List1).
re_match(alt(Rx1, Rx2), List) :- re_match(Rx1, List); re_match(Rx2, List).
re_match(star(Rx), List) :- append(List1, List2, List), re_match(Rx, List1), re_match(star(Rx), List2).

我不确定我需要做些什么改变才能让它正常工作,但我不确定还能做些什么。

此外,更改List: - append(List1,List2,List)为[H | T],其中一个示例的评估结果为true。

2 个答案:

答案 0 :(得分:7)

考虑使用DCG表示法以获得更好的可读性,并更容易推理终止属性:

:- op(100, xf, *).

rexp(eps)      --> [].
rexp([T])      --> [T].
rexp(_*)       --> [].
rexp(R*)       --> rexp(R), rexp(R*).
rexp(s(R1,R2)) --> rexp(R1), rexp(R2).
rexp((R1|R2))    --> ( rexp(R1) ; rexp(R2) ).

使用length / 2生成越来越长的列表以生成与正则表达式匹配的字符串的示例:

?- length(Ls, _), phrase(rexp(s(([a]|[b]),[c]*)), Ls).
Ls = [a] ;
Ls = [b] ;
Ls = [a, c] ;
Ls = [b, c] ;
Ls = [a, c, c] ;
etc.

答案 1 :(得分:6)

我现在无法访问SWI Prolog,但这是一个猜测:

尝试更改

re_match(star(Rx), List) :- append(List1, List2, List),
                            re_match(Rx, List1),
                            re_match(star(Rx), List2).

re_match(star(Rx), List) :- append([H|List1], List2, List),
                            re_match(Rx, [H|List1]),
                            re_match(star(Rx), List2).

强制re_match在星形构造上迭代时“吃东西”。