Разбор "сторонних" (основанных на отступах) языков - PullRequest
9 голосов
/ 01 февраля 2010

вне игры язык тот, где

... область объявлений (блок) на этом языке выражается их отступом.

Примерами таких языков являются Python, Boo, Nemerle, YAML и еще несколько.

Итак, мой вопрос заключается в следующем: как мне на самом деле их анализировать? Как решить проблему с табуляцией и пробелами (эквивалентны ли две табуляции или 8 пробелов)? Генераторы синтаксических анализаторов здесь помогают, или мне приходится самому кодировать лексер / анализатор?

Ответы [ 6 ]

8 голосов
/ 11 августа 2010

Python имеет лексер , который генерирует токены Indent и Dedent , эквивалентные фигурным скобкам ("{", "}").Существует даже пример по переполнению стека с простой реализацией такого лексера.

Для табуляции и пробелов в Python есть только кодировка соглашение : используйте 4 пробела на уровень отступа.Вкладки имеют юридический синтаксис.

4 голосов
/ 12 февраля 2010

Самый простой способ решить проблему вкладок и пробелов - это запретить комбинации пробелов и вкладок (например, это то, что сделано в F #). Любой современный редактор позволяет конвертировать вкладки в некоторое количество пробелов.

Что касается того, нужно ли вам отказываться от генераторов синтаксического анализатора, вероятно, нет, но вам придется взломать стороннюю идентификацию где-то там. Это может потребовать немного творчества с вашей стороны. Основываясь на просмотре исходного кода F #, похоже, что они используют шаг пост-лексирования для создания дополнительных токенов, представляющих элементы вне игры.

4 голосов
/ 01 февраля 2010

Как решить проблему с табуляцией и пробелами (эквивалентны ли две табуляции или 8 пробелов)?

Зависит от настроек редактора, если две вкладки будут равны восьми пробелам.

Правило офсайда, выраженное отправителем, упоминает относительное расположение двух последовательных строк кода, а не абсолютное количество пробелов. Здесь хорошее чтение, чтобы помочь вам лучше понять (и некоторые цитаты):

"Пробел имеет значение в Python исходный код. "

Нет, не в общем. Только уровень отступа ваших утверждений является значительным (то есть пробел в Слева от ваших высказываний). Везде, где нет пробелов, нет значительный и может быть использован как вы как, как и на любом другом языке. Вы также можете вставить пустые строки, которые не содержать ничего (или только произвольно пробел) где угодно.

Также точное количество отступов не имеет значения, но только Относительный отступ вложенных блоков (относительно друг друга). [...]

2 голосов
/ 05 октября 2010

Для чего бы то ни было, Haskell также основан на отступах и, необязательно, {foo; бар; и т.д.} для случаев, когда пробелы неудобны. Я написал простой синтаксический анализатор на основе отступов с Parsec , он читается как Lisp, но отступ обозначает приложение оператора. Круглые скобки можно использовать только в одной строке.

(aaa bb) cc
         e fffff (ggg hhh) iii
                 jjj kkk
         ddd

Здесь aaa применяется к bb. Какие результаты является троичной функцией. Он применяется к аргументам cc, e к одному аргументу и ddd. Посмотрите, как приложение основано на выравнивании столбцов, а не на пробелах X.

Синтаксический анализатор, вероятно, тоже может быть намного проще.

1 голос
/ 19 марта 2010

У вас есть несколько вариантов w.r.t. табуляция и пробелы: либо запрещать смешивание табуляций и пробелов, принимать фиксированное соотношение табуляций и пробелов, либо разрешить программисту выбирать для каждого проекта или для исходного файла (своего рода директива стиля #pragma tab (4) разрешить вкладки и / или изменить количество пробелов, которые они представляют).

Генератор парсеров, такой как ANTLR 3, может легко справиться с этим; Я сам играл с примером, компилируя его в цель C #. Ссылка в ответе DirkGently объясняет алгоритм Python, который напрямую переводится в код. Мой подход состоял в том, чтобы просто определить отдельные токены для пробелов и новых строк и переопределить функцию «выбросить токен», используемую лексером для вставки дополнительных маркеров отступа / отступа на лету. Это оказалось проще для реализации, чем другие подходы, которые я видел, которые переопределяют функцию «получить последний токен», но любой из них работает довольно хорошо.

0 голосов
/ 10 декабря 2013

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

Вот этот парсер: https://github.com/jiyinyiyong/cirru-parser

...