Разбор строки с «read» и игнорирование пространства имен пакета - PullRequest
0 голосов
/ 03 ноября 2018

Я пишу программу, которая открывает файл lisp, вызывает «чтение» в потоке до тех пор, пока поток не станет пустым, и работает со списками, которые он собирает.

Это работало довольно хорошо, пока я не обнаружил, что «read» выполнит поиск пакета, например, если он встретит some-package:foo, он будет жаловаться, что Package SOME-PACKAGE does not exist.

Вот пример, показывающий, что я имею в виду:

(read (make-string-input-stream "(list 'foo :foo some-package:foo)"))

Так что теперь мне бы хотелось одну из трех вещей:

  1. Сделайте так, чтобы "read" игнорировал пространства имен пакетов, чтобы я мог преобразовывать произвольные исходные файлы в списки символов.
  2. Используйте некоторую другую библиотеку синтаксического анализа с похожим поведением для «чтения», но она получает только простые символы, либо искажая :, либо игнорируя двоеточие и все, что перед ним.
  3. Предварительная обработка файла и использование регулярных выражений или чего-либо подобного для упаковки поисков и замены их простыми именами, такими как преобразование "some-package: foo" в просто "foo"

Цель всего этого в первую очередь состояла в том, чтобы создать граф зависимостей вызова функции. Я знаю, что существуют вещи такого рода гораздо более высокого качества, но я хотел сделать это самому для развлечения / обучения. Однако я столкнулся с этой проблемой и не знаю, как действовать дальше.

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Самый простой ответ - сказать читателю Lisp читать двоеточие #\: как:

(defun read-standalone-char (stream char)
  (declare (ignore stream))
  char)

(defun make-no-package-prefix-readtable (&optional (rt (copy-readtable)))
  "Return a readtable for reading while ignoring package prefixes."
  (set-syntax-from-char #\: #\Space rt)
  (set-macro-character #\: #'read-standalone-char nil rt)
  rt)

(let ((*readtable* (make-no-package-prefix-readtable)))
  (read-from-string "(list 'foo :foo some-package:foo)"))
==> (LIST 'FOO #\: FOO SOME-PACKAGE #\: FOO) ; 33

Очевидная проблема состоит в том, что это будет читать FOO:BAR и FOO :BAR одинаково, но вы можете обойти это.

0 голосов
/ 03 ноября 2018

В вашем случае вы можете обработать условие ошибки пакета, создав необходимый пакет и перезапустив его. Это также сохранит идентичность символов. Обратите внимание, что вам нужно обрабатывать in-package формы при их обнаружении.

...