아래는 C ++ 구문 분석이 (아마도) Turing-complete 인 이유에 대한 (현재) 가장 좋아하는 데모입니다 . 왜냐하면 주어진 정수가 소수 인 경우에만 구문 상 올바른 프로그램을 보여주기 때문입니다.
따라서 C ++은 컨텍스트가없고 컨텍스트에 민감하지 않다고 주장 합니다 .
프로덕션의 양쪽에 임의의 기호 시퀀스를 허용하면 Chomsky 계층 구조 에서 Type-0 문법 ( "제한되지 않음")을 생성합니다 . 이는 문맥에 맞는 문법보다 강력합니다. 무제한 문법은 Turing-complete입니다. 상황에 맞는 (유형 -1) 문법을 사용하면 제작물의 왼쪽에 여러 컨텍스트의 심볼이 허용되지만 제작의 오른쪽에 동일한 컨텍스트가 표시되어야합니다 (따라서 "문맥에 민감한"이라는 이름). 상황에 맞는 문법은 선형 경계 튜링 기계 와 동일합니다 .
예제 프로그램에서 프라임 계산은 선형 바운드 Turing machine에 의해 수행 될 수 있으므로 Turing 동등성을 입증 할 수는 없지만 구문 분석기가 구문 분석을 수행하려면 계산을 수행해야합니다. 템플릿 인스턴스화로 표현할 수있는 계산 일 수 있었으며 C ++ 템플릿 인스턴스화가 Turing-complete라고 믿는 모든 이유가 있습니다. 예를 들어 Todd L. Veldhuizen의 2003 논문을 참조하십시오 .
그럼에도 불구하고 C ++은 컴퓨터에 의해 구문 분석 될 수 있으므로 튜링 머신에 의해 구문 분석 될 수 있습니다. 결과적으로 무제한 문법으로 인식 할 수 있습니다. 실제로 이러한 문법을 작성하는 것은 실용적이지 않기 때문에 표준이 그렇게하지 않습니다. (아래 참조)
특정 표현의 "모호성"문제는 주로 붉은 청어입니다. 우선 모호성은 언어가 아닌 특정 문법의 기능입니다. 언어에 모호한 문법이없는 것으로 입증 될 수 있지만 문맥이없는 문법으로 인식 될 수 있으면 문맥이없는 것입니다. 마찬가지로 문맥이없는 문법으로는 인식 할 수 없지만 문맥에 맞는 문법으로는 인식 할 수 있으면 문맥에 민감합니다. 모호성은 관련이 없습니다.
그러나 auto b = foo<IsPrime<234799>>::typen<1>();
아래 프로그램의 21 행 (예 :)과 같은 경우에는 표현이 전혀 모호하지 않습니다. 문맥에 따라 단순히 다르게 구문 분석됩니다. 문제를 가장 간단히 표현할 때 특정 식별자의 구문 범주는 선언 된 방식 (예 : 유형 및 함수)에 따라 달라집니다. 즉, 공식 언어는 두 개의 임의 길이 문자열이 동일한 프로그램이 동일합니다 (선언 및 사용). 이것은 "복사"문법으로 모델링 할 수 있는데, 이는 동일한 단어의 연속 된 두 개의 정확한 사본을 인식하는 문법입니다. 펌핑 보조로 쉽게 증명할 수 있습니다.이 언어는 상황에 맞는 것이 아닙니다. 이 언어의 상황에 맞는 문법이 가능하며이 질문에 대한 답변으로 Type-0 문법이 제공됩니다./math/163830/context-sensitive-grammar-for-the-copy-language .
C ++를 구문 분석하기 위해 상황에 맞는 (또는 제한되지 않은) 문법을 작성하려고 시도하면 우주에 낙서를 채울 수 있습니다. C ++를 파싱하기 위해 튜링 머신을 작성하는 것은 똑같이 불가능한 일입니다. C ++ 프로그램을 작성하는 것조차 어렵고 내가 아는 한 올바른 것이 입증되지 않았습니다. 이것이 표준이 완전한 공식 문법을 제공하지 않는 이유와 구문 분석 규칙 중 일부를 기술 영어로 작성하는 이유입니다.
C ++ 표준에서 공식 문법처럼 보이는 것은 C ++ 언어 구문의 완전한 공식 정의가 아닙니다. 사전 처리 후 언어의 완전한 공식적인 정의조차 아니기 때문에 공식화가 더 쉬울 수 있습니다. (그러나 언어는 아닙니다. 표준에 의해 정의 된 C ++ 언어는 전처리기를 포함하며, 전 처리기의 동작은 문법적으로 형식적으로 표현하기가 매우 어렵 기 때문에 알고리즘으로 설명됩니다. 어휘 분해가 설명 된 표준 (한 번 이상 적용해야하는 규칙 포함)
다양한 문법 (어휘 분석을위한 두 개의 겹치는 문법, 하나는 전처리 전에 발생하고 다른 하나는 필요한 경우 이후에 "구문"문법)과 함께이 중요한 참고 사항과 함께 부록 A에 수집됩니다 (강조 추가).
이 C ++ 구문 요약은 이해를 돕기위한 것입니다. 언어에 대한 정확한 진술은 아닙니다 . 특히, 여기에 설명 된 문법 은 유효한 C ++ 구문 의 상위 집합을 허용합니다 . 표현과 선언을 구별하려면 명확성 규칙 (6.8, 7.1, 10.2)을 적용해야합니다. 또한 구문 제어가 가능하지만 의미가없는 구성을 제거하려면 액세스 제어, 모호성 및 유형 규칙을 사용해야합니다.
마지막으로 약속 된 프로그램이 있습니다. 21 행은 N in IsPrime<N>
이 소수 인 경우에만 구문 상 정확합니다 . 그렇지 않으면, typen
템플리트가 아닌 정수이므로 구문 적으로 유효한 표현식이 아니기 때문에 구문 상 올바르지 않은 것으로 구문 typen<1>()
분석됩니다 .(typen<1)>()
()
template<bool V> struct answer { answer(int) {} bool operator()(){return V;}};
template<bool no, bool yes, int f, int p> struct IsPrimeHelper
: IsPrimeHelper<p % f == 0, f * f >= p, f + 2, p> {};
template<bool yes, int f, int p> struct IsPrimeHelper<true, yes, f, p> { using type = answer<false>; };
template<int f, int p> struct IsPrimeHelper<false, true, f, p> { using type = answer<true>; };
template<int I> using IsPrime = typename IsPrimeHelper<!(I&1), false, 3, I>::type;
template<int I>
struct X { static const int i = I; int a[i]; };
template<typename A> struct foo;
template<>struct foo<answer<true>>{
template<int I> using typen = X<I>;
};
template<> struct foo<answer<false>>{
static const int typen = 0;
};
int main() {
auto b = foo<IsPrime<234799>>::typen<1>(); // Syntax error if not prime
return 0;
}
[1]보다 기술적으로 표현하려면 상황에 맞는 문법의 모든 작품은 다음과 같은 형식이어야합니다.
αAβ → αγβ
여기서 A
비 단자되고 α
, β
가능한 문법 심볼 빈 서열, 그리고 γ
비어 있지 않은 시퀀스이다. 문법 기호는 터미널 또는 비 터미널 일 수 있습니다.
A → γ
컨텍스트에서만 읽을 수 있습니다 [α, β]
. 문맥이없는 (유형 2) 문법에서, α
그리고 β
비어 있어야합니다.
"모노 토닉"제한을 사용하여 문법을 제한 할 수도 있습니다. 여기서 모든 프로덕션은 다음 형식이어야합니다.
α → β
여기서 |α| ≥ |β| > 0
( |α|
는 "길이"를 의미 α
)
단조 문법으로 인식되는 언어 세트가 상황에 맞는 문법으로 인식되는 언어 세트와 정확히 동일하다는 것을 증명할 수 있으며, 단조 문법에 근거를 두는 것이 더 쉬운 경우가 종종 있습니다. 결과적으로 "문맥"을 의미하는 것처럼 "문맥에 민감한"을 사용하는 것이 일반적입니다.