Парсер регулярных выражений, написанный в Prolog
Я уже несколько часов бьюсь головой об стену по этой домашней задаче. Мы должны проанализировать регулярное выражение с помощью 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).
Я не уверен, какие изменения мне нужно сделать, чтобы заставить его работать правильно, но я не знаю, что еще сделать.
кроме того, изменение списка :- добавить(List1, List2, List) в [H|T] не оценивается как true для одного из примеров.
2 ответов
у меня нет доступа к SWI Prolog прямо сейчас, но вот догадка:
попробуйте изменить
re_match(star(Rx), List) :- append(List1, List2, List),
re_match(Rx, List1),
re_match(star(Rx), List2).
to
re_match(star(Rx), List) :- append([H|List1], List2, List),
re_match(Rx, [H|List1]),
re_match(star(Rx), List2).
в законную силу re_match
чтобы "съесть что-то", когда он повторяется на конструкции звезды.
рассмотрите возможность использования нотации 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.