Prolog DCG для разбора экранированных последовательностей

Мне нужно разобрать строку ^borrow$ ^\$500$ в список [borrow, $500]. Грамматика, которую я написал до сих пор,

:- use_module(library(dcg/basics)).

write_list([]).
write_list([H|T]) :- atom_codes(S, H), write(S), nl, write_list(T).

% Grammar.
tags([Tag|Rest]) --> string(_), tag(Tag), tags(Rest).
tags([]) --> string(_).
tag(Tag) --> "^", tag_contents(Tag), "$".
tag_contents(Tag) --> string(Tag).

Что работает, когда у меня нет \$ внутри токена:

?- phrase(tags(T), "^pisica$ ^catel$"), write_list(T).
pisica
catel
?- phrase(tags(T), "^borrow$ ^\\$500$"), write_list(T).
borrow
\

Каков наилучший способ разбора таких экранированных последовательностей с помощью DCG Prolog?


person Andrei Sfrent    schedule 12.07.2014    source источник


Ответы (1)


проблема в том, что tag_contents//1 захватывает только обратную косую черту, а затем $ действует как остановка тега в родительском вызове.

Вот уродливый хак вокруг этой проблемы:

tag(Tag1) -->
   "^", tag_contents(Tag), [C], "$", {C \= 0'\\, append(Tag, [C], Tag1) }.

изменить

несколько лучше:

tag(Tag) --> "^", tag_contents(Tag), "$", {\+last(Tag, 0'\\)}.

изменить

«лучшая практика», конечно, заключается в обработке вложенного контента с помощью контекстных правил. Вам нужно больше кода...

tag(Tag) --> "^", tag_contents(Tag).

tag_contents([0'\\,C|Cs]) --> "\\", [C], !, tag_contents(Cs).
tag_contents([]) --> "$".
tag_contents([C|Cs]) --> [C], tag_contents(Cs).
person CapelliC    schedule 12.07.2014
comment
Извините, что испортил это, но tags//1, который использует tag//1, неверен. - person false; 13.07.2014