왼쪽 또는 오른쪽 파생 트리가 두 개 이상 있으면 문법이 모호하지만 모든 사람이 제거하기를 원하는 이유를 이해할 수 없습니다.
std::vector<std::vector<int>>
은 2011 년에 의도적으로 모호성 을 추가했으며 >>
이전 에는 공백이 필요했습니다 . 핵심 통찰력은 이러한 언어에 공급 업체보다 많은 사용자가 있다는 것이므로 사소한 성가심을 수정하면 구현자가 많은 작업을 정당화 할 수 있습니다.
왼쪽 또는 오른쪽 파생 트리가 두 개 이상 있으면 문법이 모호하지만 모든 사람이 제거하기를 원하는 이유를 이해할 수 없습니다.
std::vector<std::vector<int>>
은 2011 년에 의도적으로 모호성 을 추가했으며 >>
이전 에는 공백이 필요했습니다 . 핵심 통찰력은 이러한 언어에 공급 업체보다 많은 사용자가 있다는 것이므로 사소한 성가심을 수정하면 구현자가 많은 작업을 정당화 할 수 있습니다.
답변:
산술 표현식에 대해 다음 문법을 고려하십시오.
왼쪽에있는 한 항에있어서, 우리는 해석한다 - B를 - C 로 ( - B ) - C 일반적인 해석이다. 오른쪽에있는 한 항에있어서, 우리는 다음과 같이 해석한다 - ( B - C ) = - B + C 의도하지 무엇 아마.
프로그램을 컴파일 할 때 구문 해석이 명확해야합니다. 이를 시행하는 가장 쉬운 방법은 명확한 문법을 사용하는 것입니다. 문법이 모호한 경우, 연산자 우선 순위 및 연관성과 같은 동점 규칙을 제공 할 수 있습니다. 이러한 규칙은 문법을 특정 방식으로 모호하지 않게하여 동일하게 표현할 수 있습니다.
구문 트리 생성기를 사용하여 생성 된 구문 분석 트리 .
+
).
기존의 다른 답변 [ 1 , 2 ] 과 달리 모호한 문법이 유용한 응용 분야가 실제로 있습니다. 자연어 처리 (NLP) 분야에서 공식 문법으로 자연어 (NL)를 구문 분석하려는 경우 NL이 본질적으로 다른 수준에서 모호하다는 문제가 있습니다 [Koh18, ch. 6.4] :
구문 적 구급차 :
피터는 빨간 스포츠카에서 그 남자를 쫓았 다
피터 나 그 남자가 빨간 스포츠카에 있었습니까?
시맨틱 구급차 :
피터는 은행에 갔다
앉을 은행이나 돈을 인출 할 은행?
실용적인 구급차 :
두 남자는 두 개의 가방을 가지고
그들은 가방을 함께 가지고 있었습니까? 아니면 각 사람이 두 개의 가방을 가지고 있습니까?
NLP에 대한 다른 접근 방식은 일반적으로, 특히 이러한 구급차 처리와 다르게 처리합니다. 예를 들어 파이프 라인은 다음과 같습니다.
모든 문장에 대해이 파이프 라인을 수행하십시오. 예를 들어, 동일한 책에서 처리 한 텍스트가 많을수록 이전 문장에서 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 장 "모호성의 계산 역할"참조
모호성을 처리하는 잘 정의 된 방법이 있더라도 (예를 들어, 모호한 표현은 구문 오류 임) 이러한 문법은 여전히 문제를 일으 킵니다. 문법에 모호성을 도입하자마자 파서는 더 이상 첫 번째로 일치하는 것이 확실하다는 것을 확신 할 수 없습니다. 모호성을 배제하기 위해 명령문을 구문 분석하는 다른 모든 방법을 계속 시도해야합니다. 또한 LL (1) 언어와 같은 간단한 것을 다루지 않으므로 간단하고 작고 빠른 파서를 사용할 수 없습니다. 문법에는 여러 가지 방법으로 읽을 수있는 기호가 있으므로 많이 역 추적 할 수 있도록 준비해야합니다.
일부 제한된 도메인에서는 표현식을 구문 분석하는 가능한 모든 방법이 동일하다는 것을 증명할 수 있습니다 (예 : 연관 연산을 나타 내기 때문에). (a + b) + c = a + (b + c)입니다.
예를 들어 C ++에서 가장 까다로운 구문 분석을 수행하십시오.
bar foo(foobar());
이것은 foo
유형 의 함수 선언입니까 bar(foobar())
(매개 변수는를 반환하는 함수 포인터입니다 foobar
), 또는 foo
유형 의 변수 선언 int
이며 초기화 된 기본값으로 초기화 foobar
됩니까?
이는 매개 변수 목록 내의 표현식을 유형으로 해석 할 수없는 경우를 제외하고 첫 번째를 가정하여 컴파일러에서 차별화됩니다.
모호한 표현을 얻을 때 컴파일러에는 두 가지 옵션이 있습니다.
표현이 특정 파생이라고 가정하고 문법에 명확성을 추가하여 다른 파생을 표현할 수 있도록합니다.
어떤 식 으로든 오류가 발생하고 명확성이 필요합니다.
첫 번째는 자연스럽게 빠질 수 있고 두 번째는 컴파일러 프로그래머가 모호함에 대해 알아야합니다.
이 모호함이 감지되지 않으면 두 개의 서로 다른 컴파일러가 해당 모호한 표현에 대해 다른 파생을 기본값으로 할 수 있습니다. 명백하지 않은 이유로 코드를 이식 할 수 없게 만듭니다. 이것은 사람들이 컴파일러 중 하나의 버그라고 가정하지만 실제로 언어 사양의 결함이라고 생각합니다.
나는 그 질문에 경계선이 맞다는 가정이 있다고 생각합니다.
실제로는 모호한 문법이 아닌 모호한 문법으로 사는 것이 일반적입니다.
예를 들어, yacc로 컴파일 된 문법 (또는 들소 또는 byacc와 같은 유사한 문법)을 살펴보면 컴파일 할 때 "N shift / reduct conflict"에 관한 경고가 상당히 많이 나타납니다. yacc가 shift / reduce 충돌을 만나면 문법의 모호함을 나타냅니다.
그러나 교대 / 감소 갈등은 대개 사소한 문제입니다. 파서 생성기는 감소보다는 "시프트"를 선호하여 충돌을 해결합니다. 그것이 당신이 원하는 것이라면 문법은 완벽합니다 (실제로는 완벽하게 잘 작동하는 것처럼 보입니다).
일반적으로이 일반적인 순서에 따라 시프트 / 감소 충돌이 발생합니다 (단자에는 대문자를 사용하고 터미널에는 소문자를 사용함).
A -> B | c
B -> a | c
우리가 발생할 때 c
우리가 분석해야합니다, 모호성이있다 c
int로서 직접 A
, 또는 우리는 그것을 구문 분석해야 B
차례에 인 A
? 이런 경우 yacc 등은 더 단순하고 짧은 경로를 선택 하고 -> -> 경로로 이동하지 않고 c
직접 경로를 구문 분석 합니다. 이것은 잘못되었을 수 있지만, 그렇다면 문법에 실제로 간단한 오류가있을 수 있으므로이 옵션을 전혀 허용하지 않아야 합니다.A
c
B
A
c
A
대조적으로 우리는 다음과 같은 것을 가질 수 있습니다.
A -> B | C
B -> a | c
C -> b | c
우리가 발생할 때 이제 c
우리는 치료 여부 사이의 갈등이 c
A와 B
또는를 C
. 자동 충돌 해결 전략이 실제로 원하는 것을 선택할 가능성은 훨씬 적습니다. 이 둘 중 어느 것도 "교대"가 아니며 둘 다 "감소"이므로 "감소 / 감소 충돌"(yacc에 익숙한 사람들은 일반적으로 교대 / 감소 충돌보다 훨씬 큰 문제로 인식합니다).
그래서 나는 누군가 가 그들의 문법의 모호성을 정말로 환영 한다고 말할 정도로 확실하지는 않지만 , 적어도 어떤 경우에는 아무도 그것에 대해 전혀 신경 쓰지 않을 정도로 미미합니다. 초록에서 그들은 모든 모호성을 제거한다는 아이디어를 원할 수도 있지만 실제로 실제로는 충분하지 않습니다. 예를 들어, 약간의 모호성을 포함하는 작고 간단한 문법이 모호성을 제거하는 더 크고 복잡한 문법보다 선호 될 수 있습니다 (특히 문법에서 파서를 실제로 생성하고 모호하지 않은 것을 발견하는 실제 영역에 들어가는 경우) 문법은 대상 컴퓨터에서 실행되지 않는 파서를 생성합니다).