Jump to content

висит еще

(Перенаправлено с проблемы с висячими вещами )

Висячее else — это проблема в программировании , генераторов синтаксического анализатора в которой необязательное предложение else в операторе if-then(-else) приводит к неоднозначности вложенных условных операторов. Формально эталонная контекстно-свободная грамматика языка неоднозначна , то есть существует более одного правильного дерева разбора .

Во многих языках программирования условно исполняемый код можно писать в двух формах: в форме if-then и в форме if-then-else — предложение else не является обязательным:

if a then s
if b then s1 else s2

Это приводит к неоднозначности интерпретации при наличии вложенных операторов, особенно всякий раз, когда форма if-then появляется как s1 в форме «если-то-иначе»:

if a then if b then s else s2

В этом примере s однозначно выполняется, когда a это правда и b это правда, но можно интерпретировать s2 как исполняется, когда a ложно (таким образом присоединяя else к первому if) или когда a это правда и b является ложным (таким образом присоединяя else ко второму if). Другими словами, предыдущее утверждение можно рассматривать как одно из следующих выражений:

if a then (if b then s) else s2
if a then (if b then s else s2)

Проблема висячего другого восходит к Алголу 60 . [1] и был решен различными способами в последующих языках. В LR-парсерах висячее else является архетипическим примером конфликта сдвига-сокращения .

Избегание двусмысленности при сохранении синтаксиса

[ редактировать ]

Это проблема, которая часто возникает при построении компилятора , особенно при синтаксическом анализе без сканирования . При работе с висячим оператором else принято прикреплять его к ближайшему оператору if: [2] в частности, позволяющий использовать однозначные контекстно-свободные грамматики. Языки программирования, такие как Паскаль, [3] С [4] и Ява [5] следуйте этому соглашению, чтобы не было двусмысленности в семантике языка , хотя использование генератора синтаксического анализатора может привести к неоднозначным грамматикам . В этих случаях альтернативная группировка осуществляется явными блоками, такими как begin...end в Паскале [6] и {...} в С.

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

  • Если синтаксический анализатор создается генератором синтаксического анализатора SLR, LR(1) или LALR LR , программист часто будет полагаться на сгенерированную функцию синтаксического анализатора, предпочитая сдвиг вместо сокращения всякий раз, когда возникает конфликт. [2] Альтернативно, грамматику можно переписать, чтобы устранить конфликт, за счет увеличения размера грамматики (см. ниже ).
  • Если парсер написан вручную, программист может использовать однозначную контекстно-свободную грамматику. В качестве альтернативы можно положиться на неконтекстно-свободную грамматику или грамматику выражений синтаксического анализа .

Как избежать двусмысленности за счет изменения синтаксиса

[ редактировать ]

Проблему также можно решить, явно указав в синтаксисе связь между else и его if. Обычно это помогает избежать человеческих ошибок. [7]

Возможные решения:

  • Наличие символа «end if», ограничивающего конец конструкции if. Примерами таких языков являются ALGOL 68 , Ada , Eiffel , PL/SQL , Visual Basic , Modula-2 и AppleScript .
  • Запретить утверждение, следующее за «then», само по себе быть «if» (однако это может быть пара скобок, содержащих только предложение if-then). Этому подходу следует АЛГОЛ 60 . [8]
  • Требование фигурных скобок (круглых скобок), когда «else» следует за «if». [9]
  • Требование, чтобы каждое «если» было сопряжено с «еще». Чтобы избежать подобной проблемы, касающейся семантики, а не синтаксиса, Racket отклоняется от схемы , рассматривая if без запасного предложения считаться ошибкой, эффективно различая условные выражения (т. е. if) из условных операторов (т.е. when и unless, в которых нет запасных положений).
  • Использование разных ключевых слов для одноальтернативных и двухальтернативных операторов «если». S-алгол использует if e do s для одноальтернативного случая и if e1 then e2 else e3 для общего случая. [10]
  • Безоговорочное требование скобок, как в Swift . Это фактически верно в Python , поскольку его правила отступов ограничивают каждый блок, а не только блоки в операторах «if».

Далее следуют конкретные примеры.

В C грамматика частично гласит:

 statement = ...
    | selection-statement

 selection-statement = ...
    | IF ( expression ) statement
    | IF ( expression ) statement ELSE statement

Таким образом, без дополнительных правил утверждение

if (a) if (b) s; else s2;

может быть неоднозначно проанализирован, как если бы это было либо:

if (a)
{
  if (b)
    s;
  else
    s2;
}

или:

if (a)
{
  if (b)
    s;
}
else
  s2;

Стандарт C поясняет, что else блок связан с ближайшим if[4] . Поэтому выбирается первое дерево.

Как избежать конфликта в парсерах LR

[ редактировать ]

Приведенный выше пример можно было бы переписать следующим образом, чтобы устранить двусмысленность:

statement: open_statement
         | closed_statement
         ;

open_statement: IF '(' expression ')' statement
              | IF '(' expression ')' closed_statement ELSE open_statement
              ;

closed_statement: non_if_statement
                | IF '(' expression ')' closed_statement ELSE closed_statement
                ;

non_if_statement: ...
                ;

Любые другие грамматические правила, связанные с утверждениями, возможно, также придется дублировать таким образом, если они могут прямо или косвенно заканчиваться statement или selection-statement нетерминальный.

Однако мы даем грамматику, которая включает в себя операторы if и while.

statement: open_statement
         | closed_statement
         ;

open_statement: IF '(' expression ')' statement
              | IF '(' expression ')' closed_statement ELSE open_statement
              | WHILE '(' expression ')' open_statement
              ;

closed_statement: simple_statement
                | IF '(' expression ')' closed_statement ELSE closed_statement
                | WHILE '(' expression ')' closed_statement
                ;

simple_statement: ...
                ;

Наконец, мы даем грамматику, которая запрещает неоднозначные утверждения IF.

statement: open_statement
         | closed_statement
         ;

open_statement: IF '(' expression ')' closed_statement
              | IF '(' expression ')' open_statement
              | IF '(' expression ')' closed_statement ELSE open_statement
              | WHILE '(' expression ')' open_statement
              ;

closed_statement: simple_statement
                | IF '(' expression ')' closed_statement ELSE closed_statement
                | WHILE '(' expression ')' closed_statement
                ;

simple_statement: ...
                ;

С помощью этой грамматики утверждение if (a) if (b) c else d можно анализировать только одним способом, потому что другая интерпретация ( if (a) {if (b) c} else d) производится как

statement
open_statement
IF '(' expression ')' closed_statement ELSE open_statement
'if' '(' 'a' ')' closed_statement 'else' 'd'

и затем синтаксический анализ не удается сопоставить closed_statement на «если (b) c». Попытка с closed_statement терпит неудачу таким же образом. Другой разбор, if (a) {if (b) c else d}) удается:

statement
open_statement
IF '(' expression ')' closed_statement
IF '(' a ')' (IF '(' expression ')' closed_statement ELSE closed_statement)
IF '(' a ')' (IF '(' b ')' c ELSE 'd')

См. также

[ редактировать ]
  1. ^ Абрахамс, PW (1966). «Окончательное решение проблемы «Висячее еще» в АЛГОЛе 60 и родственных языках» . Коммуникации АКМ . 9 (9): 679–682. дои : 10.1145/365813.365821 . S2CID   6777841 .
  2. ^ Перейти обратно: а б «5.2 Конфликты смещения/сокращения» . Зубр 3.7.6 . Проверено 7 августа 2021 г. {{cite book}}: |website= игнорируется ( помогите )
  3. ^ ISO 7185:1990 (Pascal) 6.8.3.4: За оператором if без части else не должен сразу следовать токен else.
  4. ^ Перейти обратно: а б ISO 9899 :1999 (C): 6.8.4.1(3): «Другое связано с ближайшим предшествующим с лексической точки зрения, если это разрешено синтаксисом», доступно по адресу WG14 N1256 , стр. 134
  5. ^ «Спецификация языка Java, Java SE 9 Edition, 14.5. Заявления» .
  6. ^ Дейл, Нелл Б.; Уимс, Чип (ноябрь 1996 г.). «Висячее еще». Введение в Паскаль и структурированное проектирование . Джонс и Бартлетт Обучение. стр. 160–161. ISBN  9780763703974 .
  7. ^ Неоднозначность висящего else: неконтекстно-свободные грамматики семантически непрозрачны.
  8. ^ 4.5.1 Условные операторы — синтаксис в П. Науэре (ред.), Пересмотренный отчет об алгоритмическом языке ALGOL 60 , CACM 6,1, 1963, стр. 1-17
  9. ^ Неоднозначность висячего else: требуются фигурные скобки, когда else следует за if
  10. ^ Дэви, Энтони Дж.Т.; Рональд Моррисон (1981), Брайан Мик (редактор), Компиляция рекурсивного спуска , серия Эллиса Хорвуда о компьютерах и их приложениях, Чичестер, Западный Суссекс: Эллис Хорвуд, стр. 20, ISBN  0-470-27270-8
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 762421448003b61bd10d67efeedc17de__1721236920
URL1:https://arc.ask3.ru/arc/aa/76/de/762421448003b61bd10d67efeedc17de.html
Заголовок, (Title) документа по адресу, URL1:
Dangling else - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)