четверг, 31 января 2013 г.

Prolog #5.2: Построение парсера #1

Одним из полезных применений только что созданного предиката file является создание парсера. Это будет лексический парсер, и элементы языка могут быть описаны регулярной грамматикой или регулярными выражениями. В данном разделе мы напишем лекс. парсер для функционального языка (FP).
У нас две цели. Для начала, нам нужно реализовать конечный автомат, который будет принимать токены этого языка. Он будет реализован предикатом, который будет унифицироваться со “следующим” токеном во входном потоке – назовем его getToken. Далее, нам нужен предикат высокого уровня, который будет повторно (рекурсивно) ссылаться на конечный автомат (getToken) для унификации со списком токенов – мы назовем этот предикат getTokens.
Мы подойдем к парсеру в два подхода. Сначала мы рассмотрим случай, когда токены имеют фиксированную длину, в этом случае один или два символа. Затем мы рассмотрим как получить литеральные токены.

Одно и двух символьные токены

Предположим, что мы хотим распознать знак ‘+’ и вернуть токен plus. Для начала мы просто должны прочитать один символ без необходимости производить смену состояния в конечном автомате, просто для того, чтобы определить и возвратить токен и часть входного списка, которая остается.
getToken(start, [43|Rest], Rest, plus).
Помните, что список состоит из ASCII символов, так что 43 как голова списка – это символ плюс (Пролог не рассматривает целочисленные коды символов и выводимые символы как одно и то же). Заметьте, что этот клоз унифицируется только для начального состояния и кода 43. Если какой-либо другой код находится в голове списка, то будет унифицироваться другой клоз.
Другая штука о getToken. Если мы посмотрим на 4 параметра, первые два по-настоящему являются входным и выходным параметром. В понимании С++ тут нет такой же работы с вводом выводом, но интуинтивно то же самое. Так что когда запрос getToken выполняется, аргументы которые ассоциируются с двумя последующими параметрами обеспечат значения, которые попадут в следующий предикат в запросе. (В Юникс системах вы можете получить список всех ASCII кодов с помощью команды man ascii)
Токен, состоящий из двух символов может быть обработан следующим образом:
getToken(start, [63,63|Rest], Rest, equal).
Говоря о двух последних параметрах…Последний, plus или equal, это просто названное значение для токена. А первый,Rest – это чтобы использовать рекурсию можно было. Другими словами, когда обрабатывается запрос getToken, значение привязывается к Rest и будет частью входного списка, который еще не был обработан. Этот параметр затем станет вторым в следующей рекурсивной ссылке на getToken.

Комментариев нет:

Отправить комментарий