모호한 문법이 왜 나쁜가요?


30

왼쪽 또는 오른쪽 파생 트리가 두 개 이상 있으면 문법이 모호하지만 모든 사람이 제거하기를 원하는 이유를 이해할 수 없습니다.


1
관련이 있지만 동일하지는 않음 : softwareengineering.stackexchange.com/q/343872/206652 (면책 조항 : 허용 된 답변을 썼습니다)
marstato

" 명백한 문법 찾기 "도 참조하십시오 .
Rob

1
실제로, 모호하지 않은 형태는 실제 사용에 더 좋고, 모호하지 않은 형태는 적은 수의 프로덕션 규칙을 사용하여 규칙적으로 작은 트리를 작성합니다 (따라서 효율적인 컴파일러는 구문 분석하는 데 시간이 덜 걸립니다). 대부분의 도구는 명시 적으로 외부 문법으로 모호성을 해결하는 기능을 제공합니다.
Grijesh Chauhan

3
"모두 제거하고 싶어" 글쎄, 그건 사실이 아닙니다. 상업적으로 관련된 언어에서는 언어가 발전함에 따라 모호성이 추가되는 것이 일반적입니다. 예를 들어 C ++ std::vector<std::vector<int>>은 2011 년에 의도적으로 모호성 을 추가했으며 >>이전 에는 공백이 필요했습니다 . 핵심 통찰력은 이러한 언어에 공급 업체보다 많은 사용자가 있다는 것이므로 사소한 성가심을 수정하면 구현자가 많은 작업을 정당화 할 수 있습니다.
MSalters

답변:


52

산술 표현식에 대해 다음 문법을 고려하십시오.

XX+XXXXXX/Xvarconst
다음 표현식을 고려하십시오.
abc
값은 무엇입니까? 다음과 같은 두 가지 가능한 구문 분석 트리가 있습니다.

(X-X)-X 여기에 이미지 설명을 입력하십시오

왼쪽에있는 한 항에있어서, 우리는 해석한다 - B를 - C( - B ) - C 일반적인 해석이다. 오른쪽에있는 한 항에있어서, 우리는 다음과 같이 해석한다 - ( B - C ) = - B + C 의도하지 무엇 아마.abc(ab)ca(bc)=ab+c

프로그램을 컴파일 할 때 구문 해석이 명확해야합니다. 이를 시행하는 가장 쉬운 방법은 명확한 문법을 ​​사용하는 것입니다. 문법이 모호한 경우, 연산자 우선 순위 및 연관성과 같은 동점 규칙을 제공 할 수 있습니다. 이러한 규칙은 문법을 특정 방식으로 모호하지 않게하여 동일하게 표현할 수 있습니다.


구문 트리 생성기를 사용하여 생성 된 구문 분석 트리 .


12
@HIRAKMONDAL 구문이 모호하다는 사실은 실제 문제가 아닙니다. 문제는 두 개의 다른 파싱 트리가 다른 동작을한다는 것입니다. 언어에 모호한 문법이 있지만 표현에 대한 모든 구문 분석 트리가 의미 적으로 동등한 경우에는 문제가되지 않습니다 (예 : Yuval 예를 들어 유일한 연산자 인 경우 고려 +).
Bakuriu

14
@Bakuriu 당신이 말한 것은 사실이지만 "의미 적으로 동등한"것은 큰 주문입니다. 예를 들어 부동 소수점 산술은 실제로 연관되어 있지 않으므로 두 "+"트리는 동일하지 않습니다. 또한 답이 같은 방식으로 나오더라도식이 부작용을 일으킬 수있는 언어에서는 정의되지 않은 평가 순서가 중요합니다. 그래서 당신이 말한 것은 기술적으로 사실이지만 실제로 문법의 모호성이 그 문법의 사용에 영향을 미치지 않는 것은 매우 드문 일입니다.
Richard Rast

오늘날 일부 언어는 정수 오버플로를 추가로 확인하므로 정수의 a + b + c조차도 평가 순서에 따라 다릅니다.
gnasher729

3
더 나쁜 것은 어떤 경우에는 문법이 다른 의미를 얻을 수있는 방법을 제공하지 않는 것입니다. 이스케이프 문법을 선택하면 (예 : 특수 문자를 두 배로 이스케이프 처리) 특정 쿼리를 표현할 수없는 쿼리 언어에서이 문제를 보았습니다.
모니카

12

기존의 다른 답변 [ 1 , 2 ] 과 달리 모호한 문법이 유용한 응용 분야가 실제로 있습니다. 자연어 처리 (NLP) 분야에서 공식 문법으로 자연어 (NL)를 구문 분석하려는 경우 NL이 본질적으로 다른 수준에서 모호하다는 문제가 있습니다 [Koh18, ch. 6.4] :

  • 구문 적 구급차 :

    피터는 빨간 스포츠카에서 그 남자를 쫓았 다

    피터 나 그 남자가 빨간 스포츠카에 있었습니까?

  • 시맨틱 구급차 :

    피터는 은행에 갔다

    앉을 은행이나 돈을 인출 할 은행?

  • 실용적인 구급차 :

    두 남자는 두 개의 가방을 가지고

    그들은 가방을 함께 가지고 있었습니까? 아니면 각 사람이 두 개의 가방을 가지고 있습니까?

NLP에 대한 다른 접근 방식은 일반적으로, 특히 이러한 구급차 처리와 다르게 처리합니다. 예를 들어 파이프 라인은 다음과 같습니다.

  1. 모호한 문법으로 NL 구문 분석
  2. 모든 결과 AST에 대해 : 모호한 의미 적 의미를 생성하고 1 단계에서 불가능한 구문 모호성을 배제하기 위해 모델 생성을 실행하십시오.
  3. 모든 결과 모델에 대해 : 캐시에 저장하십시오.

모든 문장에 대해이 파이프 라인을 수행하십시오. 예를 들어, 동일한 책에서 처리 한 텍스트가 많을수록 이전 문장에서 3 단계까지 남은 불가능한 불필요한 모델을 더 많이 배제 할 수 있습니다.

프로그래밍 언어와 달리 모든 NL 문장에는 정확한 의미가 있어야한다는 요구 사항을 제거 할 수 있습니다. 대신, 더 큰 텍스트를 파싱하는 동안 여러 가능한 의미 론적 모델을 예약 할 수 있습니다. 때때로 통찰력은 우리가 이전의 모호성을 배제하는 데 도움이됩니다.

파서가 모호한 문법에 대해 여러 파생물을 출력 할 수있게함으로써 손을 더럽 히고 싶다면 Grammatical Framework를 살펴보십시오 . 또한 [Koh18, ch. 5]에는 위의 파이프 라인과 비슷한 것을 보여주는 소개가 있습니다. [Koh18]은 강의 노트이므로 노트가 강의 없이는 이해하기 쉽지 않을 수 있습니다.


참고 문헌

[Koh18] : Michael Kohlhase. "논리 기반 자연 언어 처리. 겨울 학기 2018/19. 강의 노트." URL : https://kwarc.info/teaching/LBS/notes.pdf . 과정 설명의 URL : https://kwarc.info/courses/lbs/ (독일어)

[Koh18, ch. 5] : [Koh18]의 5 장 "조각 구현 : 문법 및 논리 프레임 워크"참조

[Koh18, ch. 6.4] [Koh18]의 6.4 장 "모호성의 계산 역할"참조


고마워요 .. 나는 같은 의심을 가지고 있었고 그것을 정리했다. : :)
HIRAK MONDAL

1
문제 언급하지 않는 버팔로 버팔로 버팔로 버팔로 버팔로 버팔로 ... 버팔로의 적절한 수의
하겐 폰 Eitzen

당신은“대조”라고 쓰지만, 나는 이것을 내가 대답 한 것의 다른 쪽이라고 부릅니다. 모호한 문법으로 자연어를 파싱하는 것은 너무 어려워서 전통적인 파서는 할 수 없습니다!
Davislor

1
@ComFreek 더 정확해야합니다. GF (Thanks for the link!)를 간략하게 살펴보면 3 개의 확장 (예 : 중복 제거)이 포함 된 컨텍스트없는 문법을 읽고 가능한 모든 파생 목록을 반환합니다. 그렇게하는 알고리즘은 50 년대부터 존재 해 왔습니다. 그러나 완전 일반 CFG를 처리 할 수 ​​있다는 것은 최악의 경우 런타임이 급격히 증가 함을 의미하며 실제로 GLL과 같은 일반 파서를 사용하더라도 소프트웨어 엔지니어는 LL 문법과 같은 CFG의 하위 집합을 사용하려고합니다. 보다 효율적으로 파싱됩니다.
Davislor

1
@ComFreek 따라서 컴퓨터가 CFG를 처리 할 수있는 것은 아닙니다 (자연어에는 실제로 컨텍스트가없고 실제로 유용한 기계 번역이 완전히 다른 기술을 사용하지만). 파서가 모호성을 처리 해야하는 경우 더 효율적으로 만들 수있는 특정 바로 가기를 배제한다는 것입니다.
Davislor

10

모호성을 처리하는 잘 정의 된 방법이 있더라도 (예를 들어, 모호한 표현은 구문 오류 임) 이러한 문법은 여전히 ​​문제를 일으 킵니다. 문법에 모호성을 도입하자마자 파서는 더 이상 첫 번째로 일치하는 것이 확실하다는 것을 확신 할 수 없습니다. 모호성을 배제하기 위해 명령문을 구문 분석하는 다른 모든 방법을 계속 시도해야합니다. 또한 LL (1) 언어와 같은 간단한 것을 다루지 않으므로 간단하고 작고 빠른 파서를 사용할 수 없습니다. 문법에는 여러 가지 방법으로 읽을 수있는 기호가 있으므로 많이 역 추적 할 수 있도록 준비해야합니다.

일부 제한된 도메인에서는 표현식을 구문 분석하는 가능한 모든 방법이 동일하다는 것을 증명할 수 있습니다 (예 : 연관 연산을 나타 내기 때문에). (a + b) + c = a + (b + c)입니다.


9

합니까의 IF a THEN IF b THEN x ELSE y평균

IF a THEN
    IF b THEN
        x
    ELSE
        y

또는

IF a THEN
    IF b THEN x
ELSE
    y

? 일명 매달려 다른 문제 .


1
모호하지 않은 문법조차도 (Java, C, C ++ 등에서와 같이) 인간의 관점에서 명백한 (!) 모호성을 허용한다는 것을 보여주는 좋은 예입니다. 공식적으로나 계산적으로는 훌륭하지만 UX / 버그가없는 개발 문제가 더 생겼습니다.
ComFreek

5

예를 들어 C ++에서 가장 까다로운 구문 분석을 수행하십시오.

bar foo(foobar());

이것은 foo유형 의 함수 선언입니까 bar(foobar())(매개 변수는를 반환하는 함수 포인터입니다 foobar), 또는 foo유형 의 변수 선언 int이며 초기화 된 기본값으로 초기화 foobar됩니까?

이는 매개 변수 목록 내의 표현식을 유형으로 해석 할 수없는 경우를 제외하고 첫 번째를 가정하여 컴파일러에서 차별화됩니다.

모호한 표현을 얻을 때 컴파일러에는 두 가지 옵션이 있습니다.

  1. 표현이 특정 파생이라고 가정하고 문법에 명확성을 추가하여 다른 파생을 표현할 수 있도록합니다.

  2. 어떤 식 으로든 오류가 발생하고 명확성이 필요합니다.

첫 번째는 자연스럽게 빠질 수 있고 두 번째는 컴파일러 프로그래머가 모호함에 대해 알아야합니다.

이 모호함이 감지되지 않으면 두 개의 서로 다른 컴파일러가 해당 모호한 표현에 대해 다른 파생을 기본값으로 할 수 있습니다. 명백하지 않은 이유로 코드를 이식 할 수 없게 만듭니다. 이것은 사람들이 컴파일러 중 하나의 버그라고 가정하지만 실제로 언어 사양의 결함이라고 생각합니다.


5

나는 그 질문에 경계선이 맞다는 가정이 있다고 생각합니다.

실제로는 모호한 문법이 아닌 모호한 문법으로 사는 것이 일반적입니다.

예를 들어, yacc로 컴파일 된 문법 (또는 들소 또는 byacc와 같은 유사한 문법)을 살펴보면 컴파일 할 때 "N shift / reduct conflict"에 관한 경고가 상당히 많이 나타납니다. yacc가 shift / reduce 충돌을 만나면 문법의 모호함을 나타냅니다.

그러나 교대 / 감소 갈등은 대개 사소한 문제입니다. 파서 생성기는 감소보다는 "시프트"를 선호하여 충돌을 해결합니다. 그것이 당신이 원하는 것이라면 문법은 완벽합니다 (실제로는 완벽하게 잘 작동하는 것처럼 보입니다).

일반적으로이 일반적인 순서에 따라 시프트 / 감소 충돌이 발생합니다 (단자에는 대문자를 사용하고 터미널에는 소문자를 사용함).

A -> B | c
B -> a | c

우리가 발생할 때 c우리가 분석해야합니다, 모호성이있다 cint로서 직접 A, 또는 우리는 그것을 구문 분석해야 B차례에 인 A? 이런 경우 yacc 등은 더 단순하고 짧은 경로를 선택 하고 -> -> 경로로 이동하지 않고 c직접 경로를 구문 분석 합니다. 이것은 잘못되었을 수 있지만, 그렇다면 문법에 실제로 간단한 오류가있을 수 있으므로이 옵션을 전혀 허용하지 않아야 합니다.AcBAcA

대조적으로 우리는 다음과 같은 것을 가질 수 있습니다.

A -> B | C
B -> a | c
C -> b | c

우리가 발생할 때 이제 c우리는 치료 여부 사이의 갈등이 cA와 B또는를 C. 자동 충돌 해결 전략이 실제로 원하는 것을 선택할 가능성은 훨씬 적습니다. 이 둘 중 어느 것도 "교대"가 아니며 둘 다 "감소"이므로 "감소 / 감소 충돌"(yacc에 익숙한 사람들은 일반적으로 교대 / 감소 충돌보다 훨씬 큰 문제로 인식합니다).

그래서 나는 누군가 가 그들의 문법의 모호성을 정말로 환영 한다고 말할 정도로 확실하지는 않지만 , 적어도 어떤 경우에는 아무도 그것에 대해 전혀 신경 쓰지 않을 정도로 미미합니다. 초록에서 그들은 모든 모호성을 제거한다는 아이디어를 원할 수도 있지만 실제로 실제로는 충분하지 않습니다. 예를 들어, 약간의 모호성을 포함하는 작고 간단한 문법이 모호성을 제거하는 더 크고 복잡한 문법보다 선호 될 수 있습니다 (특히 문법에서 파서를 실제로 생성하고 모호하지 않은 것을 발견하는 실제 영역에 들어가는 경우) 문법은 대상 컴퓨터에서 실행되지 않는 파서를 생성합니다).


5 개월 전에 교대 축소 갈등에 대한이 훌륭한 설명을 받았으면 좋겠다. ^^; +1
HotelCalifornia
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.