Реализация «включает» при разборе в Attoparsec - PullRequest
0 голосов
/ 03 февраля 2019

Я пишу DSL для удовольствия.Я решил использовать attoparsec, потому что я был знаком с ним.

Я хочу реализовать разбор включений с относительными именами файлов, например:

include /some/dir/file.ext

или URL:

include http://blah.com/my/file.ext

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

Проблема заключается в том, что, хотя синтаксический анализ этих операторов простЯ не могу запустить IO (как я понимаю) в моих синтаксических анализаторах Attoparsec.

Как мне использовать Attoparsec для достижения этой цели?Должен ли я разделить начальный ввод, используя некоторую строковую фильтрацию, а затем разобрать каждый «блок» в parse и feed соответственно?По сути, двухпроходный подход к анализу?

1 Ответ

0 голосов
/ 03 февраля 2019

Attoparsec является чистым (Data.Attoparsec.Internal.Types.Parser не является преобразователем и не включает IO), поэтому вы правы, что вы не можете расширять включения непосредственно из анализатора.

Разделение синтаксического анализатора на два прохода кажется правильным подходом: один проход действует как препроцессор C, принимая файл с операторами include, чередующимися с другими вещами.«Прочие вещи» должны быть в основном лексически верными, а не ваш полный синтаксический анализатор - точно так же, как препроцессор C заботится только о токенах и соответствующих скобках, а не о других скобках или чем-либо семантическом.Затем вы заменяете включаемые файлы, создавая полностью развернутый файл, который вы можете передать существующему анализатору.

Если включаемый файл должен быть в некотором смысле синтаксически «автономным» , то вы можетеСначала проанализируйте весь файл, чередуя его с include s, а затем замените их.Например:

-- Whatever items you’re parsing.
data Item

-- A reference to an included path.
data Include = Include FilePath

parse :: Parser [Either Include Item]

-- Substitute includes; also calls ‘parse’
-- recursively until no includes remain.
substituteIncludes :: [Either Include Item] -> IO [Item]

Скажите, если вы просто используете attoparsec для лексических токенов, которые в любом случае не могут пересекать границы файла, или вы выполняете полный анализ, но хотите disallow включаемый файл, который содержит, например, несопоставленные скобки.


Другой вариант заключается в непосредственном внедрении IO в ваш анализатор с использованием другой библиотеки синтаксического анализа, такой как megaparsec, которая обеспечиваетParsecT преобразователь, который вы можете обернуть вокруг IO, чтобы сделать IO прямо в вашем парсере.Я бы, вероятно, сделал это для прототипа, но кажется более уместным максимально разделить проблемы синтаксического анализа и расширения.

...