달랑달리다

Dangling else

dangling else는 if-then(–else) 스테이트먼트의 옵션 else 절이 중첩된 조건을 애매하게 만드는 파서 제너레이터프로그래밍 문제입니다.형식적으로 언어의 참조 컨텍스트프리 문법은 모호하며, 이는 하나 이상의 올바른 해석 트리가 있음을 의미합니다.

많은 프로그래밍 언어에서는 조건부로 실행되는 코드를 if-then 형식과 if-then-else 형식의 두 가지 형식으로 작성할 수 있습니다.다른 구문은 옵션입니다.

ab이면 s1이 되고, 그렇지 않으면 s2가 된다.

이는 중첩된 문장이 있을 때, 특히 if-then 형식이 다음과 같이 나타날 때 해석에 모호성을 야기합니다.s1if-then-then-then-time 형식으로 지정합니다.

a경우 b의 경우 s2의 경우

이 예에서는,s명확하게 실행된다.a사실이고b사실이지만 해석할 수 있다s2언제 실행되는지 여부afalse(다른 것을 첫 번째 if에 부가할 수 없음) 또는 다음 경우a사실이고b는 false 입니다(다른 것을 두 번째 if에 부가하는 것을 제외합니다).즉, 앞의 문장은 다음 표현 중 하나로 볼 수 있습니다.

a의 경우 s2의 경우 a의 경우 s2의 경우 b의 경우 s2의 경우 s의 경우 s2의 경우

그 이외의 문제는 ALGOL [1]60으로 거슬러 올라가 후속 언어로 다양한 방법으로 해결되었습니다.LR 파서에서는 매달림 other가 시프트 리듀스 충돌의 전형적인 예입니다.

구문을 유지하면서 모호성 회피

이는 컴파일러 구성, 특히 스캐너 없는 구문 분석에서 자주 발생합니다.행잉 그 외를 다룰 때는 다른 것을 가까운 if [2]문에 붙이는 것이 관례이며, 특히 문맥이 명확하지 않은 문법을 사용할 수 있습니다.Pascal,[3] C[4][5] Java와 같은 프로그래밍 언어는 이 규칙을 따르기 때문에 파서 생성기를 사용하면 문법이 모호해질 수 있지만 언어의 의미론에는 모호함이 없습니다.이러한 경우 대체 그룹화는 다음과 같은 명시적 블록에 의해 이루어집니다.begin...endPascal[6]{...}주식회사.

컴파일러의 구축 방법에 따라서는 애매모호함을 피하기 위해 다음과 같은 수정 조치를 취할 수 있습니다.

  • 파서가 SLR, LR(1) 또는 LALR LR 파서 제너레이터에 의해 생성되는 경우 프로그래머는 [2]종종 충돌이 발생할 때마다 시프트 오버 리덕션을 선호하는 생성된 파서 기능에 의존합니다.또는 문법을 다시 작성하여 경합을 제거할 수 있습니다(아래 참조).
  • 파서가 손으로 쓰여져 있는 경우 프로그래머는 문맥이 명확하지 않은 문법을 사용할 수 있습니다.또는 문맥이 없는 문법과 구문해석식 문법에 의존해도 좋다.

구문을 변경하여 애매모호함을 회피하다

이 문제는 구문 내에서 other와 if 사이의 링크를 명시적으로 함으로써 해결할 수도 있습니다.이것은 보통 사람의 [7]실수를 피하는 데 도움이 됩니다.

생각할 수 있는 솔루션은 다음과 같습니다.

  • if 구성의 끝을 구분하는 "if 종료" 기호가 있습니다.이러한 언어의 예로는 ALGOL 68, Ada, Effel, PL/SQL, Visual Basic, Modula-2, AppleScript 등이 있습니다.
  • "then" 뒤에 오는 문장은 "if" 그 자체가 될 수 없습니다(단, if-then-clause만 포함하는 문 괄호 쌍일 수 있습니다). 어프로치는 ALGOL [8]60에 따릅니다.
  • "else" 뒤에 "if"[9]가 이어지는 경우 중괄호(부모 크기 조정)가 필요합니다.
  • 모든 "if"를 "else"와 쌍으로 구성해야 합니다.구문보다는 의미론에 관한 유사한 문제를 피하기 위해, Racket은 scheme에서 벗어납니다.if오류인 폴백 절 없이 효과적으로 조건식을 구별한다(예:if조건문(예:when그리고.unless(폴백구는 없습니다).
  • 하나의 대안 문장과 두 개의 대안 "if" 문장에 서로 다른 키워드를 사용합니다.S-algol 사용if e do s일안일안일안일단일안일안일안할경우if e1 then e2 else e3일반 [10]케이스에 대해서요.
  • 스위프트처럼 무조건 교정기가 필요해이것은 Python의 들여쓰기 규칙이 "if" 문장의 블록뿐만 아니라 모든 블록을 구분하기 때문에 사실상 사실이다.

구체적인 예는 다음과 같습니다.

C

C에서 문법은 부분적으로 다음과 같다.

스테이트먼트 = ...selection-statement selection-statement = ...IF ( expression )스테이트먼트 IF ( expression )스테이트먼트 ELSE 스테이트먼트

따라서, 추가 규칙 없이, 그 진술은

한다면 (a) 한다면 (b) s; 또 다른 s2; 

다음과 같이 애매하게 해석할 수 있습니다.

한다면 (a) {   한다면 (b)     s;   또 다른     s2; } 

또는 다음과 같이 입력합니다.

한다면 (a) {   한다면 (b)     s; } 또 다른   s2; 

실제로 C에서는 첫 번째 트리가 선택됩니다.else가장 가까운 곳에if.

LR 파서의 경합을 회피하다

위의 예는 애매함을 해소하기 위해 다음과 같이 고쳐 쓸 수 있습니다.

스테이트먼트: open_statement closed_statement; open_statement:IF '(' 식 ')' 문 IF '(' 식 ')' closed_statement ELSE open_statement, closed_if_statement IF '(' 식 ')' closed_else closed_statement, non_if_statement: ...;

다른 문장과 관련된 문법 규칙도 직접 또는 간접적으로 다음과 같이 끝날 수 있는 경우 이 방법으로 복제되어야 할 수 있습니다.statement또는selection-statement비단말기

그러나 우리는 if 문장과 while 문장이 모두 포함된 문법을 제공한다.

스테이트먼트: open_statement closed_statement; open_statement:IF '(' 식 ')' 문 IF '(')' closed_statement ELSE open_statement WHY '(' 식 ')', closed_statement IF '(' 식 ')', closed_statement IF '(' 식 ')', closed_statement; 심플_스테이트먼트: ...;

마지막으로 애매한 IF 문장이 금지되는 문법을 제시합니다.

스테이트먼트: open_statement closed_statement; open_statement:if '(' 식 ')', simple_statement IF '(' 식 ')', open_statement IF '(' 식 ')', closed_statement IF '(' 식 ')', closed_statement IF '(' 식 ')', closed_statement IF '(')', closed_stated_statement WHILE ' ( ' 식 ' ) closed _ statement ; simple _ statement : ...;

"if (a) if (b) c else d"가 실패하는 경우:

statement open_statement IF '(' 식 ')' closed_ELSE open_statement 'if' '(' 'a' ')' closed_statement 'else' 'd'

그 후 파싱이 실패하여closed_statement"if (b) c"까지.에 의한 시도closed_statement같은 방법으로 실패합니다.

「 」를 참조해 주세요.

레퍼런스

  1. ^ Abrahams, P. W. (1966). "A final solution to the Dangling else of ALGOL 60 and related languages". Communications of the ACM. 9 (9): 679–682. doi:10.1145/365813.365821. S2CID 6777841.
  2. ^ a b "5.2 Shift/Reduce Conflicts". Bison 3.7.6. GNU Operating System. Retrieved 2021-08-07.
  3. ^ ISO 7185:1990(Pascal) 6.8.3.4: else-part가 없는 if-statement에는 토큰이 즉시 뒤따르지 않는다.
  4. ^ ISO 9899:1999 (C): 6.8.4.1(3): "다른 것은 구문에 의해 허용된 경우 앞의 어휘적으로 가장 가까운 것과 관련지어져 있습니다." WG14 N1256, 페이지 134에서 구할 수 있습니다.
  5. ^ "The Java Language Specification, Java SE 9 Edition, 14.5. Statements".
  6. ^ Dale, Nell B.; Weems, Chip (November 1996). "Dangling Else". Introduction to Pascal and Structured Design. pp. 160–161. ISBN 9780763703974.
  7. ^ 매달림 이외의 애매성: 문맥이 없는 문법은 의미상 불투명합니다.
  8. ^ 4.5.1 조건문: P의 구문.Nauer(ed), 알고리즘 언어 ALGOL 60, CACM 6,1, 1963년 1-17페이지 개정 보고서
  9. ^ 매달림 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