Использование Goto в лексере / парсере - PullRequest
2 голосов
/ 30 июня 2011

У меня есть пара лексер / синтаксический анализатор (которую я отобрал у кого-то еще много лет назад).Я собираюсь добавить пару функций и подумал, что сначала должен стандартизировать использование while (true), содержащего несколько if / else if / else против переключателя, который использует goto для перехода назад до переключателя.

(До того, как пламя начнется, я обычно не использую goto как зло и т. Д. И т. Д.)

Проблема со значением time (true) и вложенным переключателем заключается в том, что разрыв происходит только изкоммутатор и не может выйти из этого режима.

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

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

Текущий способ использования синтаксического анализатора if / else if / else вместо внутреннего переключателя, но у меня есть предпочтение для переключателя, если это возможно.

Код лексера в общем, кажется, обходит это, удаляя while (true) и помещая метку непосредственно перед запуском коммутатора и используя goto для продолжения цикла.Это оставляет разрыв, означающий остановку цикла, и, если честно, кажется, что это самый чистый путь, но он включает в себя идиотическое движение.

Возвращаясь к тому времени (верно), я также вижу третий путь.Используйте метку после while (true) и позвольте коду коммутатора использовать goto, чтобы добраться до него, когда цикл должен закончиться.Прерывание означало бы выход из коммутатора, но продолжение цикла.

Так что же это за панели?Goto слишком отвратителен для использования?Или это нормально, когда есть только одна метка, к которой можно перейти, что уменьшает отступы и дает в противном случае понятный код?Должны ли парсеры / лексеры получить специальную лицензию на использование gotos?

Я могу предоставить пример кода, если это поможет.

Ответы [ 2 ]

3 голосов
/ 30 июня 2011

Использование GOTO дисциплинированными способами прекрасно. Языки, которые не допускают разрывы произвольно вложенных блочных структур, приводят к тому, что этот вопрос неоднократно поднимался, начиная с 1970-х годов, когда люди задавали вопрос «какие структуры потока управления должен иметь язык» до смерти. (Примечание: эта жалоба не является особенной для лексеров / парсеров).

Вам не нужна схема с логическим значением; это просто добавляет дополнительные издержки к проверкам цикла и загромождает код.

Я думаю, у вас есть эта проблема:

   <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  <want to break out all blocks>
             ...
                            }
                       }

Правильное лекарство с хорошим языком:

  blocks_label:
  <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  exit blocks_label;
             ...
                            }
                       }

, если на вашем языке существует конструкция exit , она завершается блоки, помеченные именованным ярлыком. (Там нет оправданий для современного языка не иметь этого, но тогда я не дизайн их).

Совершенно удовлетворительно писать, как заменитель бедного человека:

   <if/while/loop head> {
       <if/while/loop head> {
             ...
                 if <cond>  goto exit_these_blocks;
             ...
                            }
                       }
   exit_these_blocks:  // my language doesn't have decent block exits

Иногда вы найдете язык, который предлагает

break <exp>

, где exp - обычно постоянное целое число, означающее "разбить exp вложенных блоков". Это поразительно глупая идея, так как какой-то плохой сопровождающий позже может вставить другой блок где-нибудь в стеке, и теперь код делает сумасшедшие вещи. (Фактически, эта точная ошибка в телефонном коммутаторе вывела всю телефонную систему Восточного побережья около 20 лет назад). Если вы видите эту конструкцию в своем языке, используйте заменитель бедняка.

2 голосов
/ 30 июня 2011

В парсерах использование GOTO вполне разумно. Когда вы переходите к базовому уровню, все циклы, условия и т. Д. Реализуются как gotos, потому что это то, что могут делать процессоры - «взять следующую команду, которая будет выполняться отсюда».

Единственные проблемы с gotos и причина, по которой их так часто демонизируют, заключается в том, что они могут быть признаком неструктурированного кода, возникающего из неструктурированного мышления. В современных языках высокого уровня нет необходимости в gotos, потому что все средства доступны, чтобы хорошо структурировать код, а хорошо структурированный код подразумевает, по крайней мере, некоторое структурированное мышление.

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

...