Отметьте верные утверждения для языка программирования паскаль в условном операторе перед else знак

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

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

если a то s if b then s1 else s2 

Это приводит к двусмысленности в интерпретации. Когда существуют вложенные операторы. Особенно когда форма if-then появляется как

s1в форме if-then-else:

если a то если b то s еще s2 

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

если a, то (если b, то s) еще s2 если a, то (если b, то s еще s2) 

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

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

Эта проблема часто возникает при построении компилятора, особенно при синтаксическоманализе без сканирования . Соглашение при работе с висячим else заключается в том. Чтобы присоединить else к соседнему оператору if[2], в частности. Допускающему однозначные контекстно-свободные грамматики. Языки программирования. Такие как Pascal,[3] C[4] и Java[5], следуют этому соглашению. Поэтому нет никакой двусмысленности в семантике

языка, хотя использование генератора синтаксического анализатора может привести к двусмысленным грамматикам. В этих случаях альтернативная группировка выполняется явными блоками. Такими как begin...endв Pascal[6] и {...}в C.

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

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

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

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

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

Возможные решения таковы:

  • Наличие оператора Примерами таких языков являются

    ALGOL 68, Ada, Eiffel, PL/SQL, Visual Basicи AppleScript.

  • Запрещение оператору. Следующему за Этому подходу следует ALGOL 60.]
  • Требование скобок (скобок), когда ]
  • Требуя, чтобы каждое Racket отклоняется от Схемы, рассматривая ifпредложение без запасного предложения как ошибку. Эффективно отличая условные выражения (то есть if) от условных операторов (то есть whenи unless, которые не имеют резервных предложений).
  • Использование различных ключевых слов для одно-альтернативных и двух-альтернативных операторов S-algol используется if e do sкак для одноальтернативного случая, так и

    if e1 then e2 else e3для общего случая.[10]

  • Требующие брекетов безоговорочно. Как Swift и Modula-2. Это фактически верно в Python, поскольку его правила отступа ограничивают каждый блок. А не только те. Которые содержатся в операторах Чтобы уменьшить возникающий беспорядок, Modula-2 избавляется от открывателя блоков на нефункциональных уровнях.

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

C

В Cграмматика читается. В частности:

 заявление = ... | selection-statement selection-statement = ... Оператор | IF ( expression ) | IF ( expression ) оператор ELSE оператор

Таким образом. Без дальнейших правил утверждение

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

можно было бы двусмысленно разобрать. Как если бы это было либо:

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

или:

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

На практике в С выбирается первое дерево. Связывая elseего с ближайшим if.

Избегание конфликта в парсерах LR

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

заявление: open_statement | closed_statement ; open_statement: IF '(' expression ')' оператор | 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.

заявление: open_statement | closed_statement ; open_statement: оператор IF '(' expression ')' | 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.

заявление: open_statement | closed_statement ; open_statement: IF '(' expression ')' simple_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: ... ;

При этом грамматический разбор

заявление open_statement IF '(' expression ')' closed_statement ELSE open_statement 'if' ' (''a'') ' closed_statement 'else' 'd' 

и тогда синтаксический анализ терпит неудачу. Пытаясь соответствовать closed_statementПопытка с closed_statementтаким же успехом проваливается.

  1. ^
  2. ^ b 5.2 Shift/Reduce Conflicts с веб-сайта операционной системы GNU
  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. ^ .
  6. ^ Pascal, Nell Dale and Chip Weems, p. 160-161
  7. ^ Двусмысленность болтающегося else: неконтекстно-свободные грамматики семантически непрозрачны
  8. ^ 4.5.1 Условные операторы — Синтаксис в P. Nauer (ред.), Пересмотренный отчет об алгоритмическом языке ALGOL 60, CACM 6,1, 1963 стр. 1-17
  9. ^ Двусмысленность болтающегося else: требуйте скобок. Когда else следует, если
  10. ^ Davie, Antony J. T.; Ronald Morrison (1981), Brian Meek (ed.), Recursive Descent Compiling, Ellis Horwood series in computers and their applications, Chichester. West Sussex: Ellis Horwood, p. 20,

    ISBN 0-470-27270-8