Удаление пробелов из строк в Прологе

Я написал парсер в прологе. Я еще не закончил. Это часть кода. Следующим шагом является уничтожение всех пробелов в строке.

parse(Source, Tree) :-  kill_whitespace(Source, CleanInput), % remove whitespaces
                        actual_parse(CleanInput, Tree).

actual_parse(CleanInput, Tree):- phrase(expr(Tree),CleanInput).

expr(Ast) --> term(Ast1), expr_(Ast1,Ast).
expr_(Acc,Ast) --> " + ", !, term(Ast2), expr_(plus(Acc,Ast2), Ast).
expr_(Acc,Ast) --> " - ", !, term(Ast2), expr_(minus(Acc,Ast2), Ast).
expr_(Acc,Acc) --> [].

term(Ast) --> factor(Ast1), term_(Ast1,Ast).
term_(Acc,Ast) --> " * ", !, factor(Ast2), term_(mul(Acc,Ast2),Ast).
term_(Acc,Ast) --> " ** ", !, factor(Ast2), term_(pol(Acc,Ast2),Ast).
term_(Acc,Acc) --> [].

factor(Ast) --> "(", !, expr(Ast), ")".
factor(D)--> [X], { X >= 48 , X=<57 , D is X-48 }.
factor(id(N,E)) --> "x", factor(N), ":=", expr(E), ";".

Например:

?- parse("x2:=4",T).
    T = id(2, 4)

Правда! Но когда я пишу:

?- parse("x2 := 4",T).
false.

Это должно быть также верно, и это должен быть фильтр: kill_whitespace(Source, CleanInput),

Различные решения неэффективны. Как я могу это сделать?

3 ответа

Решение

Я обычно помещаю "пропустить" нетерминал, где может появиться место. Такой пропуск обычно отбрасывает комментарии, а также любой другой "неинтересный" текст.

Чтобы сделать как можно проще:

% discard any number of spaces
s --> "" ; " ", s.

Я предпочитаю короткое имя, чтобы сохранить грамматику в чистоте. Для удаления новых строк и т. Д., А также:

s --> "" ; (" ";"\t";"\n";"\r"), s.

Примечание "стиля": вместо

parse(Source, Tree) :-
   expr(Tree, Source, []).

вы могли бы рассмотреть

parse(Source, Tree) :-
   phrase(expr(Tree), Source).

Что ж, самый простой способ - это проанализировать строку и удалить пробелы / оставить только не-пробелы с предикатом фильтра. Но это требует второго разбора.

Другой способ исправить это - использовать собственный предикат для "получения" символов,
т.е. foo --> "a". становится foo --> get("a"). где get//1 это что-то вроде:

get(X) --> [X].
get(X) --> whitespace, get(X).

Обычный способ написания парсера - это написать его в два этапа:

На первом этапе проводится лексический анализ и производится поток токенов. Пробелы и другие "токены", не имеющие значения для синтаксического анализа (например, комментарии), отбрасываются в этот момент.

Второй этап проводит сам анализ, изучая список токенов, произведенных лексическим анализатором.

Другие вопросы по тегам