C ++에 컨텍스트가 없거나 컨텍스트에 민감합니까?
나는 종종 C ++이 상황에 맞는 언어라는 주장을 듣는다. 다음 예를 보자.
a b(c);
변수 정의 또는 함수 선언입니까? 그것은 상징의 의미에 달려 c
있습니다. 경우 c
A는 변수가 다음 a b(c);
라는 변수 정의 b
유형을 a
. 로 직접 초기화됩니다 c
. 하지만 c
A는 유형 , 다음 a b(c);
라는 함수 선언 b
을 소요 c
하고를 반환합니다 a
.
문맥없는 언어의 정의를 찾아 보면 기본적으로 모든 문법 규칙에 정확히 하나의 비단 말 기호로 구성된 왼쪽이 있어야한다는 것을 알 수 있습니다. 반면 상황에 맞는 문법은 왼쪽에 임의의 문자열 및 비 터미널 기호 문자열을 허용합니다.
"C ++ 프로그래밍 언어"의 부록 A를 살펴보면 왼쪽에 터미널이 아닌 단일 기호 외에 다른 문법 규칙이 없었습니다. 그것은 C ++에 컨텍스트가 없음을 의미합니다. 물론, 모든 문맥이없는 언어는 문맥이없는 언어가 상황에 맞는 언어의 하위 세트를 형성한다는 점에서 문맥에 민감하지만, 요점이 아닙니다.
그렇다면 C ++ 컨텍스트가 없거나 컨텍스트에 민감합니까?
아래는 C ++ 구문 분석이 (아마도) Turing-complete 인 이유에 대한 (현재) 가장 좋아하는 데모입니다 . 왜냐하면 주어진 정수가 소수 인 경우에만 구문 상 올바른 프로그램을 보여주기 때문입니다.
따라서 C ++은 컨텍스트가없고 컨텍스트에 민감하지 않다고 주장 합니다 .
프로덕션의 양쪽에 임의의 심볼 시퀀스를 허용하면 Chomsky 계층 구조 에서 Type-0 문법 ( "제한되지 않음")을 생성합니다 . 이는 문맥에 맞는 문법보다 강력합니다. 무제한 문법은 Turing-complete입니다. 상황에 맞는 (Type-1) 문법을 사용하면 제작물의 왼쪽에 여러 컨텍스트의 심볼이 허용되지만 제작의 오른쪽에 동일한 컨텍스트가 표시되어야합니다 (따라서 "문맥에 민감한"이라는 이름). [1] 상황에 맞는 문법은 선형 경계 튜링 기계 와 같습니다 .
예제 프로그램에서 프라임 계산은 선형 경계 튜링 머신에 의해 수행 될 수 있으므로 튜링 동등성을 증명할 수는 없지만 구문 분석기가 구문 분석을 수행하려면 계산을 수행해야합니다. 템플릿 인스턴스화로 표현할 수있는 계산 일 수 있었으며 C ++ 템플릿 인스턴스화가 Turing-complete라고 믿는 모든 이유가 있습니다. 예를 들어 Todd L. Veldhuizen의 2003 논문을 참조하십시오 .
그럼에도 불구하고 C ++은 컴퓨터에 의해 구문 분석 될 수 있으므로 튜링 머신에 의해 구문 분석 될 수 있습니다. 결과적으로 무제한 문법으로 인식 할 수 있습니다. 실제로 이러한 문법을 작성하는 것은 실용적이지 않기 때문에 표준이 그렇게하지 않습니다. (아래 참조)
특정 표현의 "모호성"문제는 주로 붉은 청어입니다. 우선 모호성은 언어가 아닌 특정 문법의 기능입니다. 언어에 명확한 문법이없는 것으로 입증 될 수 있더라도 문맥이없는 문법으로 인식 될 수 있으면 문맥이없는 것입니다. 마찬가지로 문맥이없는 문법으로는 인식 할 수 없지만 문맥에 맞는 문법으로는 인식 할 수 있으면 문맥에 민감합니다. 모호성은 관련이 없습니다.
그러나 auto b = foo<IsPrime<234799>>::typen<1>();
아래 프로그램의 21 행 (예 :)과 같은 경우에는 표현이 전혀 모호하지 않습니다. 문맥에 따라 단순히 다르게 구문 분석됩니다. 문제의 가장 간단한 표현에서 특정 식별자의 구문 범주는 선언 된 방식 (예 : 유형 및 함수)에 따라 달라집니다. 즉, 공식 언어는 두 개의 임의 길이 문자열이 동일한 프로그램이 동일합니다 (선언 및 사용). 이것은 "복사"문법으로 모델링 할 수 있는데, 이는 동일한 단어의 연속 된 두 개의 정확한 사본을 인식하는 문법입니다. 펌핑 보조로 쉽게 증명할 수 있습니다.이 언어는 문맥에 맞지 않습니다. 이 언어의 상황에 맞는 문법이 가능하며이 질문에 대한 답변으로 Type-0 문법이 제공됩니다. https://math.stackexchange.com/questions/163830/context-sensitive-grammar-for-the- 복사 언어 .
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) 문법에서, α
그리고 β
비어 있어야합니다.
"모노 닉 (monotonic)"제한을 사용하여 문법을 제한 할 수도 있습니다. 여기서 모든 프로덕션은 다음 형식이어야합니다.
α → β
여기서 |α| ≥ |β| > 0
( |α|
는 "길이"를 의미 α
)
단조 문법으로 인식되는 언어 세트가 상황에 맞는 문법으로 인식되는 언어 세트와 정확히 동일하다는 것을 증명할 수 있으며, 단조 문법에 근거를 두는 것이 더 쉬운 경우가 종종 있습니다. 결과적으로 "문맥"을 의미하는 것처럼 "문맥에 민감한"을 사용하는 것이 일반적입니다.
첫째, 당신은 당연히 문법 그래서, C ++ 표준의 끝에 문법에는 상황에 맞는 규칙이 없다는 관측 이다 문맥 자유.
그러나이 문법은 다음과 같은 비 C ++ 프로그램을 생성하기 때문에 C ++ 언어를 정확하게 설명하지 않습니다.
int m() { m++; }
또는
typedef static int int;
"잘 구성된 C ++ 프로그램 세트"로 정의 된 C ++ 언어는 문맥에 맞지 않습니다 (선언 할 변수 만 요구한다는 것을 보여줄 수 있습니다). 이론적으로 템플릿으로 Turing-complete 프로그램을 작성하고 그 결과에 따라 잘못된 프로그램을 만들 수 있다고 가정하면 상황에 따라 달라지지 않습니다.
이제 (무지한) 사람들 (일반적으로 언어 이론가는 아니지만 파서 디자이너)은 일반적으로 다음과 같은 의미에서 "컨텍스트가없는"을 사용합니다.
- 모호한
- 들소와 파싱 할 수 없습니다
- LL (k), LR (k), LALR (k) 또는 그들이 선택한 파서 정의 언어 클래스가 아님
표준 뒤의 문법은 이러한 범주를 만족시키지 못합니다 (즉, LL (k) ...가 아니라 모호합니다). 그래서 C ++ 문법은 "문맥이 없습니다". 그리고 어떤 의미에서, 그들은 작동하는 C ++ 파서를 생성하는 것이 어렵다는 것이 옳습니다.
여기에 사용 된 속성은 컨텍스트가없는 언어와 약하게 연결되어 있습니다. 모호성은 컨텍스트 감도와 관련이 없으며 (실제로 컨텍스트 구분 규칙은 일반적으로 제작을 명확하게하는 데 도움이 됨) 다른 두 개는 컨텍스트의 하위 집합 일뿐입니다. 무료 언어. 컨텍스트없는 언어를 구문 분석하는 것은 선형 프로세스가 아닙니다 (결정적 구문을 구문 분석하는 것임).
예. 다음 표현식은 유형 확인 컨텍스트 에 따라 다른 순서로 조작 됩니다 .
편집 : 실제 작업 순서가 다를 경우, 꾸미기 전에 AST를 파싱하는 "일반"컴파일러를 사용하기가 매우 어렵습니다 (유형 정보 전파). 언급 된 상황에 민감한 다른 것들은 이것에 비해 "쉬운"것입니다 (템플릿 평가가 전혀 쉬운 것은 아닙니다).
#if FIRST_MEANING
template<bool B>
class foo
{ };
#else
static const int foo = 0;
static const int bar = 15;
#endif
뒤에 :
static int foobar( foo < 2 ? 1 < 1 : 0 > & bar );
질문에 대답하려면 두 가지 다른 질문을 구별해야합니다.
거의 모든 프로그래밍 언어의 구문은 컨텍스트가 없습니다. 일반적으로 확장 된 Backus-Naur 양식 또는 컨텍스트가없는 문법으로 제공됩니다.
그러나 프로그램이 프로그래밍 언어로 정의 된 문맥없는 문법을 준수하더라도 반드시 유효한 프로그램 일 필요는 없습니다 . 유효한 프로그램이 되려면 프로그램이 만족해야하는 많은 문맥이없는 poperty가 있습니다. 예를 들어, 가장 간단한 속성은 변수의 범위입니다.
결론적으로 C ++에 컨텍스트가 없는지 여부는 묻는 질문에 따라 다릅니다.
예 C ++은 상황에 민감하고 상황에 매우 민감합니다. 컨텍스트 프리 파서를 사용하여 파일을 간단히 구문 분석하여 구문 트리를 빌드 할 수없는 경우가 있습니다. 경우에 따라 이전 지식에서 기호를 결정해야합니다 (예 : 구문 분석 중에 심볼 테이블 작성).
첫 번째 예 :
A*B;
이것이 곱셈 표현입니까?
또는
이것은 B
변수 의 선언이 유형의 포인터 A
입니까?
A가 변수이면 표현식이고 A가 유형이면 포인터 선언입니다.
두 번째 예 :
A B(bar);
함수 프로토 타입이 타입의 인수를 취 bar
합니까?
또는
이것은 B
유형의 변수 를 선언 하고 초기화 자로 상수를 사용하여 A
A의 생성자를 호출 bar
합니까?
bar
기호 테이블의 변수인지 또는 유형 인지 다시 알아야 합니다.
세 번째 예 :
class Foo
{
public:
void fn(){x*y;}
int x, y;
};
x와 y의 선언이 함수 정의 뒤에 오기 때문에 구문 분석하는 동안 기호 테이블을 작성하는 것이 도움이되지 않는 경우입니다. 따라서 클래스 정의를 먼저 스캔하고 두 번째 단계에서 메소드 정의를 살펴보고 x * y가 포인터 선언이 아닌 표현식이라는 것을 말해야합니다.
Bjarne Stroustrup 의 C ++의 디자인 및 진화를 살펴볼 수 있습니다 . 여기에는 yacc (또는 유사한)를 사용하여 초기 버전의 C ++을 구문 분석하고 재귀 적 하강을 대신 사용하려는 그의 문제가 설명되어 있습니다.
C ++은 GLR 파서로 구문 분석됩니다. 즉, 소스 코드를 구문 분석하는 동안 구문 분석기 가 모호함을 발견 할 수 있지만 나중에 사용할 문법 규칙을 계속 결정해야합니다 .
또한 봐
C ++을 LR (1) 파서로 파싱 할 수없는 이유는 무엇입니까?
문맥없는 문법 은 프로그래밍 언어 구문의 모든 규칙을 설명 할 수는 없습니다 . 예를 들어, 속성 문법은 표현식 유형의 유효성을 검사하는 데 사용됩니다.
int x;
x = 9 + 1.0;
당신은 할 수없는 문맥 자유 문법 다음과 같은 규칙을 설명 : 과제의 오른쪽은 왼쪽의 동일한 유형이어야합니다.
나는 "문맥에 민감한"의 공식적인 정의와 "문맥에 민감한"의 비공식적 인 사용 사이에 약간의 혼동이 있다고 생각한다. 전자는 잘 정의 된 의미를 갖습니다. 후자는 "입력을 구문 분석하기 위해 컨텍스트가 필요합니다"라고 말하는 데 사용됩니다.
이것은 또한 여기에 묻습니다 : 문맥 감도 대 모호성 .
상황에 맞는 문법은 다음과 같습니다.
<a> ::= <b> | <c>
<b> ::= "x"
<c> ::= "x"
입력 "x"를 구문 분석하려면 컨텍스트가 필요하거나 모호함을 느끼거나 "경고 : E8271-입력이 모호합니다. 115 행"을 출력해야합니다. 그러나 상황에 맞는 문법은 아닙니다.
알골과 유사한 언어는 문맥에 따라 달라지지 않습니다. 식에 따라 식별자가 표시 될 수있는 식과 명령문을 제한하는 규칙이 있으며 선언과 사용간에 발생할 수있는 명령문의 수에는 제한이 없기 때문입니다.
일반적인 해결책은 실제로 유효한 프로그램의 상위 세트를 허용하고 컨텍스트에 민감한 부분 을 규칙에 첨부 된 임시 "시맨틱"코드에 넣는 컨텍스트없는 구문 분석기를 작성하는 것 입니다.
C ++은 Turing-complete 템플릿 시스템 덕분에 이보다 훨씬 뛰어납니다. 스택 오버플로 질문 794015를 참조하십시오 .
진실 :)
스탠리 워 포드 컴퓨터 시스템 . 341-346 쪽.
a b(c);
두 개의 유효한 구문 분석 선언과 변수 가 있으므로 상황에 따라 다릅니다. "If c
is a type" 이라고 말하면 바로 문맥입니다. C ++이 그 유형에 어떻게 민감한 지 정확하게 설명했습니다. "무엇입니까 c
?" 라는 문맥이 없다면 이것을 명확하게 파싱 할 수 없었습니다.
여기서 컨텍스트는 토큰 선택으로 표현됩니다. 구문 분석기는 유형의 이름을 지정하면 식별자를 유형 이름 토큰으로 읽습니다. 이것은 가장 간단한 해결 방법이며 상황에 따라 달라지는 복잡한 작업을 피합니다 (이 경우).
편집 : 물론 상황 민감도에 대한 더 많은 문제가 있으며, 나는 당신이 보여준 것에 중점을 두었습니다. 템플릿은 특히 불쾌합니다.
C ++ 표준의 제작물은 상황에 맞게 작성되지만, 우리 모두가 알고 있듯이 언어를 정확하게 정의하지는 않습니다. 대부분의 사람들이 현재의 언어로 모호하다고 생각하는 것 중 일부는 상황에 맞는 문법으로 명확하게 해결할 수 있습니다.
가장 확실한 예를 들어, 가장 Vexing 구문 분석을 고려하십시오 int f(X);
. 경우 X
의 값,이 정의이다 f
으로 초기화 될 변수로 X
. X
유형 인 경우 유형 f
의 단일 매개 변수를 사용하는 함수로 정의 합니다 X
.
문법적인 관점에서 보면 다음과 같이 볼 수 있습니다.
A variable_decl ::= <type> <identifier> '(' initializer ')' ';'
B function_decl ::= <type> <identifier> '(' param_decl ')' ';'
A ::= [declaration of X as value]
B ::= [declaration of X as type]
물론, 완전히 정확하려면 다른 유형의 선언을 중재 할 가능성을 설명하기 위해 추가 "물건"을 추가해야합니다 (즉, A와 B는 모두 "X의 선언을 포함하여 선언 ..."이어야 함) 또는 그 순서에 맞는 것).
이것은 여전히 전형적인 CSG와는 다소 다릅니다 (또는 적어도 내가 기억하는 것). 이는 구성되고있는 기호 테이블에 따라 달라집니다.이 부분은 X
앞의 문장 유형뿐만 아니라 올바른 기호 / 식별자에 대한 올바른 문장 유형입니다.
따라서, 나는 확실하게 찾고자 노력해야하지만, 즉각적인 추측은 적어도 용어가 일반적으로 사용되는 것처럼 이것이 실제로 CSG 자격을 갖추지 못한다는 것입니다.
문맥이없는 문법의 가장 간단한 경우는 템플릿과 관련된 표현식을 구문 분석하는 것입니다.
a<b<c>()
이것은 다음 중 하나로 구문 분석 할 수 있습니다
template
|
a < expr > ()
|
<
/ \
b c
또는
expr
|
<
/ \
a template
|
b < expr > ()
|
c
두 AST는 'a'선언을 검사하여 명확하게 설명 할 수 있습니다. 'a'가 템플릿 인 경우 이전 AST, 그렇지 않은 경우에는 AST입니다.
때때로 더 나 빠진다 : 사람들이 C ++에 "결정할 수없는 문법"이 있다고 말할 때 무엇을 의미 하는가?
C ++ 템플릿은 Turing Powerful 인 것으로 나타났습니다. 공식적인 참고 자료는 아니지만 다음과 같은 점을 고려해야합니다.
http://cpptruths.blogspot.com/2005/11/c-templates-are-turing-complete.html
나는 추측을 할 것이다. (60 년대의 ALGOL이 CFG에 의해 재현 될 수 없다는 것을 보여주는 민속적이고 간결한 CACM 증거만큼 오래되었다) C ++은 CFG에 의해서만 정확하게 구문 분석 될 수 없다고 말한다. CFG, 트리 패스 또는 축소 이벤트 중 다양한 TP 메커니즘과 함께-이것은 또 다른 이야기입니다. 일반적으로 Halting 문제로 인해 정확 / 잘못된 것으로 표시 될 수 없지만 그럼에도 불구하고 정확하지 않은 C ++ 프로그램이 있습니다.
{PS- Meta-S의 저자로서 (위의 여러 사람들에 의해 언급 된)-가장 확실하게 Thothic은 기능이 없으며 소프트웨어를 무료로 사용할 수 없다고 말할 수 있습니다. 아마도이 버전의 응답을 삭제하거나 -3으로 투표하지 않도록이 버전의 응답을 사용했습니다.}
C ++에는 컨텍스트가 없습니다. 얼마 전에 컴파일러 강의에서 배웠습니다. "검색어 또는 의미론"섹션에서 C 및 C ++에 컨텍스트가없는 이유를 설명하는 빠른 검색에서이 링크를 제공했습니다.
감사합니다, 오
바네스
분명히, 질문을 그대로 사용하면 식별자가있는 거의 모든 언어가 상황에 따라 다릅니다.
식별자가 형식 이름 (클래스 이름, typedef에 의해 도입 된 이름, typename 템플릿 매개 변수)인지, 템플릿 이름 또는 식별자의 일부를 올바르게 사용할 수있는 다른 이름인지 알아야합니다. 예를 들어 :
x = (name)(expression);
name
유형 이름 인 경우 캐스트이고 name
함수 이름 인 경우 함수 호출 입니다. 또 다른 경우는 변수 정의와 함수 선언을 구별 할 수없는 소위 "가장 vexing 구문 분석"입니다 (함수 선언이라고하는 규칙이 있습니다).
그 어려움의 필요성 도입 typename
및 template
의존 이름을. 나머지 C ++은 내가 아는 한 문맥에 민감하지 않습니다 (즉, 문맥에 맞는 문법을 작성할 수 있습니다).
Meta-S "는 Quinn Tyler Jackson의 상황에 맞는 구문 분석 엔진입니다. 사용하지는 않았지만 인상적인 이야기를 들려줍니다. comp.compilers에서 자신의 의견을 확인하고 rnaparse.com/MetaS%20defined.htm을 참조하십시오. – Ira Baxter 7 월 25 일 10:42
올바른 링크는 수수께끼를 파싱합니다
Meta-S는 Thothic이라는 기능이없는 회사의 자산이었습니다. Meta-S의 무료 사본을 관심있는 사람에게 보낼 수 있으며 rna 파싱 연구에 사용했습니다. 예제 폴더에 포함 된 "pseudoknot grammar"는 비 생물 정보학, 미숙 한 프로그래머가 작성했으며 기본적으로 작동하지 않습니다. 저의 문법은 다른 접근법을 취하고 잘 작동합니다.
여기서 중요한 문제는 "문맥이없는"과 "문맥에 민감한"이라는 용어가 컴퓨터 과학에서 조금 직관적이지 않다는 것입니다. C ++의 경우 컨텍스트 감도는 모호성과 비슷하지만 일반적인 경우에는 반드시 그런 것은 아닙니다.
C / ++에서 if 문은 함수 본문 내에서만 허용됩니다. 상황에 맞는 것 같아요? 음 ... 아니. 문맥이없는 문법은 실제로 어떤 코드 줄을 뽑아서 그것이 유효한지 결정할 수있는 속성이 필요하지 않습니다. 실제로 컨텍스트가없는 것은 아닙니다. 그것은 실제로 그 소리와 관련이있는 것을 막연하게 암시하는 레이블 일뿐입니다.
이제 함수 본문 내의 명령문이 경우와 같이 직접적인 문법 조상 외부에 정의 된 내용 (예 : 식별자가 유형 또는 변수를 설명하는지 여부)에 따라 다르게 구문 분석되는 a * b;
경우 실제로 컨텍스트에 민감합니다. 여기에는 실제 모호성이 없습니다. a
유형이 포인터이면 포인터 선언으로 해석되고 그렇지 않으면 곱셈입니다.
상황에 맞는 것이 반드시 "파싱하기 어렵다"는 것은 아닙니다. 악명 높은 a * b;
"모호성"은 typedef
이전에 발생한 기호 테이블을 사용하여 해결할 수 있기 때문에 C는 실제로 그렇게 어렵지 않습니다 . C ++과 같은 경우를 해결하기 위해 튜링 완료로 입증 된 임의의 템플릿 인스턴스화가 필요하지 않습니다. C ++과 동일한 컨텍스트 감도를 가지고 있지만 유한 한 시간 내에 컴파일되지 않는 C 프로그램을 실제로 작성할 수는 없습니다.
파이썬 (및 기타 공백에 민감한 언어)도 들여 쓰기 및 욕설 토큰을 생성하기 위해 어휘 분석기의 상태가 필요하기 때문에 상황에 따라 다릅니다. 그러나 일반적인 LL-1 문법보다 구문 분석하기가 더 어렵지는 않습니다. 실제로 파서 생성기를 사용하는데, 이는 파이썬이 정보가없는 구문 오류 메시지를 갖는 이유의 일부입니다. 여기서는 a * b;
파이썬 에서 문제 와 같은 "모호성"이 없다는 점에 주목하는 것이 중요합니다 (첫 번째 단락에서 언급 한대로) "모호한"문법이없는 상황에 맞는 언어의 구체적인 예를 제공합니다.
이 답변은 C ++에 컨텍스트가 없음을 말합니다 ... 응답자가 아닌 구문 분석 할 수 없다는 의미가 있으며 특정 상수가 아닌 경우 잘못된 C ++ 프로그램을 생성하는 어려운 코드 예제를 제공합니다. 소수.
다른 사람들이 관찰 한 것처럼, 언어 가 상황 에 맞는지 / 없는지에 대한 질문은 특정 문법에 대한 동일한 질문과 다릅니다.
구문 분석 가능성에 대한 질문을 설정하기 위해 C ++에 대한 문맥이없는 문법이 있다는 사실을 실증적 증거로 제시합니다. 실제로는 기존 GLR로 구문 분석하여 원본 텍스트의 문맥이없는 구문 분석을위한 AST를 생성하는 데 사용할 수 있습니다. 문법에 의해 구동되는 파서 기반 도구입니다.
그렇습니다. "너무 많은 것을 받아들이면"성공합니다. 허용되는 모든 것이 유효한 C ++ 프로그램이 아니기 때문에 추가 검사 (유형 검사)가 뒤 따릅니다. 그리고 예, 타입 체커는 계산 문제에 부딪 칠 수 있습니다. 실제로 도구에는이 문제가 없습니다. 사람들이 그런 프로그램을 작성했다면 아무도 컴파일하지 않을 것입니다. (표준은 실제로 템플릿을 펼칠 수있는 계산량을 제한한다고 생각합니다. 실제로 계산은 실제로 유한하지만 아마도 상당히 큽니다).
의미 하는 바, 소스 프로그램이 유효한 C ++ 소스 프로그램 세트의 멤버인지 판별하면 문제가 훨씬 더 어렵다는 데 동의합니다. 그러나 그것이 문제라는 것은 파싱 하지 않습니다 .
이 도구는 구문 분석 된 프로그램의 유형 검사에서 구문 분석을 분리하여이 문제를 해결합니다. 컨텍스트가없는 상태에서 여러 가지 해석이있는 경우 여러 구문 분석이 가능한 구문 분석 트리에 모호성 노드가 기록됩니다 . 유형 검사는 어느 것이 올바른지 결정하고 유효하지 않은 하위 트리를 제거합니다. 아래 예제에서 (부분) 구문 분석 트리를 볼 수 있습니다. 전체 트리가 너무 커서 SO 답변에 맞지 않습니다. 값 234797 또는 234799가 사용되는지 여부에 상관없이 구문 분석 트리가 나타납니다.
원래 값 234799로 AST에서 도구 이름 / 유형 분석기를 실행하면 성공합니다. 값이 234797 인 경우 이름 분석기는 "typen is a type."이라는 오류 메시지와 함께 실패합니다 (예상대로). 따라서 해당 버전은 유효한 C ++ 프로그램이 아닙니다.
967 tree nodes in tree.
15 ambiguity nodes in tree.
(translation_unit@Cpp~GCC5=2#6b11a20^0 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
(declaration_seq@Cpp~GCC5=1021#6b06640^1#6b11a20:1 {10} Line 1 Column 1 File C:/temp/prime_with_templates.cpp
(pp_declaration_seq@Cpp~GCC5=1022#6b049a0^1#6b06640:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
(declaration@Cpp~GCC5=1036#6b04980^1#6b049a0:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
|(template_declaration@Cpp~GCC5=2079#6b04960^1#6b04980:1 Line 1 Column 1 File C:/temp/prime_with_templates.cpp
| (template_parameter_list@Cpp~GCC5=2082#6afbde0^1#6b04960:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| (template_parameter@Cpp~GCC5=2085#6afbd80^1#6afbde0:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| (parameter_declaration@Cpp~GCC5=1611#6afbd40^1#6afbd80:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| |(basic_decl_specifier_seq@Cpp~GCC5=1070#6afb880^1#6afbd40:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| | (decl_specifier@Cpp~GCC5=1073#6afb840^1#6afb880:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| | (trailing_type_specifier@Cpp~GCC5=1118#6afb7e0^1#6afb840:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp
| | (simple_type_specifier@Cpp~GCC5=1138#6afb7a0^1#6afb7e0:1 Line 1 Column 10 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | )trailing_type_specifier#6afb7e0
| | )decl_specifier#6afb840
| |)basic_decl_specifier_seq#6afb880
| |(ptr_declarator@Cpp~GCC5=1417#6afbc40^1#6afbd40:2 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
| | (noptr_declarator@Cpp~GCC5=1421#6afbba0^1#6afbc40:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
| | (declarator_id@Cpp~GCC5=1487#6afbb80^1#6afbba0:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
| | (id_expression@Cpp~GCC5=317#6afbaa0^1#6afbb80:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
| | |(unqualified_id@Cpp~GCC5=319#6afb9c0^1#6afbaa0:1 Line 1 Column 15 File C:/temp/prime_with_templates.cpp
| | | (IDENTIFIER@Cpp~GCC5=3368#6afb780^1#6afb9c0:1[`V'] Line 1 Column 15 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | |)unqualified_id#6afb9c0
| | )id_expression#6afbaa0
| | )declarator_id#6afbb80
| | )noptr_declarator#6afbba0
| |)ptr_declarator#6afbc40
| )parameter_declaration#6afbd40
| )template_parameter#6afbd80
| )template_parameter_list#6afbde0
| (declaration@Cpp~GCC5=1033#6b04940^1#6b04960:2 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| (block_declaration@Cpp~GCC5=1050#6b04920^1#6b04940:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| (simple_declaration@Cpp~GCC5=1060#6b04900^1#6b04920:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| |(basic_decl_specifier_seq@Cpp~GCC5=1070#6b048e0^1#6b04900:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| | (decl_specifier@Cpp~GCC5=1073#6b048c0^1#6b048e0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| | (type_specifier@Cpp~GCC5=1110#6b048a0^1#6b048c0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| | (class_specifier@Cpp~GCC5=1761#6b04880^1#6b048a0:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| | |(class_head@Cpp~GCC5=1763#6afb980^1#6b04880:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp
| | | (class_key@Cpp~GCC5=1791#6afbca0^1#6afb980:1 Line 1 Column 18 File C:/temp/prime_with_templates.cpp)class_key
| | | (IDENTIFIER@Cpp~GCC5=3368#6afbcc0^1#6afb980:2[`answer'] Line 1 Column 25 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | (optional_base_clause@Cpp~GCC5=1872#6afba60^1#6afb980:3 Line 1 Column 32 File C:/temp/prime_with_templates.cpp)optional_base_clause
| | |)class_head#6afb980
| | |(member_specification@Cpp~GCC5=1794#6b042e0^1#6b04880:2 {2} Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | (member_declaration_or_access_specifier@Cpp~GCC5=1806#6b04060^1#6b042e0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | (member_declaration@Cpp~GCC5=1822#6b04040^1#6b04060:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | (function_definition@Cpp~GCC5=1632#6b04020^1#6b04040:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | |(function_head@Cpp~GCC5=1673#6afbec0^1#6b04020:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | (ptr_declarator@Cpp~GCC5=1417#6afbfe0^1#6afbec0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | (noptr_declarator@Cpp~GCC5=1422#6afbf80^1#6afbfe0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | (noptr_declarator@Cpp~GCC5=1421#6afbf60^1#6afbf80:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | |(declarator_id@Cpp~GCC5=1487#6afbea0^1#6afbf60:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | | (id_expression@Cpp~GCC5=317#6afbb40^1#6afbea0:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | | (unqualified_id@Cpp~GCC5=319#6afbc80^1#6afbb40:1 Line 1 Column 34 File C:/temp/prime_with_templates.cpp
| | | | | (IDENTIFIER@Cpp~GCC5=3368#6afbc20^1#6afbc80:1[`answer'] Line 1 Column 34 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | | | )unqualified_id#6afbc80
| | | | | )id_expression#6afbb40
| | | | |)declarator_id#6afbea0
| | | | )noptr_declarator#6afbf60
| | | | (parameter_declaration_clause@Cpp~GCC5=1559#6afbd00^1#6afbf80:2 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | |(pp_parameter_declaration_list@Cpp~GCC5=1570#6afb940^1#6afbd00:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | (pp_parameter_declaration_seq@Cpp~GCC5=1574#6afb800^1#6afb940:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | (parameter_declaration@Cpp~GCC5=1610#6afb9a0^1#6afb800:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | (basic_decl_specifier_seq@Cpp~GCC5=1070#6afbf40^1#6afb9a0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | |(decl_specifier@Cpp~GCC5=1073#6afbfa0^1#6afbf40:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | | (trailing_type_specifier@Cpp~GCC5=1118#6afbfc0^1#6afbfa0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp
| | | | | | (simple_type_specifier@Cpp~GCC5=1140#6afb860^1#6afbfc0:1 Line 1 Column 41 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | | | | | )trailing_type_specifier#6afbfc0
| | | | | |)decl_specifier#6afbfa0
| | | | | )basic_decl_specifier_seq#6afbf40
| | | | | )parameter_declaration#6afb9a0
| | | | | )pp_parameter_declaration_seq#6afb800
| | | | |)pp_parameter_declaration_list#6afb940
| | | | )parameter_declaration_clause#6afbd00
| | | | (function_qualifiers@Cpp~GCC5=1438#6afbce0^1#6afbf80:3 Line 1 Column 46 File C:/temp/prime_with_templates.cpp)function_qualifiers
| | | | )noptr_declarator#6afbf80
| | | | )ptr_declarator#6afbfe0
| | | |)function_head#6afbec0
| | | |(function_body@Cpp~GCC5=1680#6b04000^1#6b04020:2 Line 1 Column 46 File C:/temp/prime_with_templates.cpp
| | | | (compound_statement@Cpp~GCC5=888#6afbee0^1#6b04000:1 Line 1 Column 46 File C:/temp/prime_with_templates.cpp)compound_statement
| | | |)function_body#6b04000
| | | )function_definition#6b04020
| | | )member_declaration#6b04040
| | | )member_declaration_or_access_specifier#6b04060
| | | (member_declaration_or_access_specifier@Cpp~GCC5=1806#6b042c0^1#6b042e0:2 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | (member_declaration@Cpp~GCC5=1822#6b04820^1#6b042c0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | (function_definition@Cpp~GCC5=1632#6b04280^1#6b04820:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | |(function_head@Cpp~GCC5=1674#6b04220^1#6b04280:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b040e0^1#6b04220:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | | (decl_specifier@Cpp~GCC5=1073#6b040c0^1#6b040e0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | | (trailing_type_specifier@Cpp~GCC5=1118#6b040a0^1#6b040c0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp
| | | | |(simple_type_specifier@Cpp~GCC5=1138#6b04080^1#6b040a0:1 Line 1 Column 49 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | | | )trailing_type_specifier#6b040a0
| | | | )decl_specifier#6b040c0
| | | | )basic_decl_specifier_seq#6b040e0
| | | | (ptr_declarator@Cpp~GCC5=1417#6b04200^1#6b04220:2 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | (noptr_declarator@Cpp~GCC5=1422#6b041e0^1#6b04200:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | (noptr_declarator@Cpp~GCC5=1421#6b041a0^1#6b041e0:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | |(declarator_id@Cpp~GCC5=1487#6b04180^1#6b041a0:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | | (id_expression@Cpp~GCC5=317#6b04160^1#6b04180:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | | (unqualified_id@Cpp~GCC5=320#6b04140^1#6b04160:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | | (operator_function_id@Cpp~GCC5=2027#6b04120^1#6b04140:1 Line 1 Column 54 File C:/temp/prime_with_templates.cpp
| | | | | |(operator@Cpp~GCC5=2070#6b04100^1#6b04120:1 Line 1 Column 62 File C:/temp/prime_with_templates.cpp)operator
| | | | | )operator_function_id#6b04120
| | | | | )unqualified_id#6b04140
| | | | | )id_expression#6b04160
| | | | |)declarator_id#6b04180
| | | | )noptr_declarator#6b041a0
| | | | (parameter_declaration_clause@Cpp~GCC5=1558#6afba40^1#6b041e0:2 Line 1 Column 65 File C:/temp/prime_with_templates.cpp)parameter_declaration_clause
| | | | (function_qualifiers@Cpp~GCC5=1438#6b041c0^1#6b041e0:3 Line 1 Column 66 File C:/temp/prime_with_templates.cpp)function_qualifiers
| | | | )noptr_declarator#6b041e0
| | | | )ptr_declarator#6b04200
| | | |)function_head#6b04220
| | | |(function_body@Cpp~GCC5=1680#6b04300^1#6b04280:2 Line 1 Column 66 File C:/temp/prime_with_templates.cpp
| | | | (compound_statement@Cpp~GCC5=889#6b04760^1#6b04300:1 Line 1 Column 66 File C:/temp/prime_with_templates.cpp
| | | | (pp_statement_seq@Cpp~GCC5=894#6b04780^1#6b04760:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
| | | | (statement@Cpp~GCC5=857#6b04440^1#6b04780:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
| | | | |(jump_statement@Cpp~GCC5=1011#6afba80^1#6b04440:1 Line 1 Column 67 File C:/temp/prime_with_templates.cpp
| | | | | (pm_expression@Cpp~GCC5=551#6b04380^1#6afba80:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | (cast_expression@Cpp~GCC5=543#6b04360^1#6b04380:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | (unary_expression@Cpp~GCC5=465#6b04340^1#6b04360:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | |(primary_expression@Cpp~GCC5=307#6b04320^1#6b04340:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | | (id_expression@Cpp~GCC5=317#6b042a0^1#6b04320:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | | (unqualified_id@Cpp~GCC5=319#6b04260^1#6b042a0:1 Line 1 Column 74 File C:/temp/prime_with_templates.cpp
| | | | | | (IDENTIFIER@Cpp~GCC5=3368#6b04240^1#6b04260:1[`V'] Line 1 Column 74 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | | | | )unqualified_id#6b04260
| | | | | | )id_expression#6b042a0
| | | | | |)primary_expression#6b04320
| | | | | )unary_expression#6b04340
| | | | | )cast_expression#6b04360
| | | | | )pm_expression#6b04380
| | | | |)jump_statement#6afba80
| | | | )statement#6b04440
| | | | )pp_statement_seq#6b04780
| | | | )compound_statement#6b04760
| | | |)function_body#6b04300
| | | )function_definition#6b04280
| | | )member_declaration#6b04820
| | | )member_declaration_or_access_specifier#6b042c0
| | |)member_specification#6b042e0
| | )class_specifier#6b04880
| | )type_specifier#6b048a0
| | )decl_specifier#6b048c0
| |)basic_decl_specifier_seq#6b048e0
| )simple_declaration#6b04900
| )block_declaration#6b04920
| )declaration#6b04940
|)template_declaration#6b04960
)declaration#6b04980
)pp_declaration_seq#6b049a0
(pp_declaration_seq@Cpp~GCC5=1022#6b06620^1#6b06640:2 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
(declaration@Cpp~GCC5=1036#6b06600^1#6b06620:1 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
|(template_declaration@Cpp~GCC5=2079#6b065e0^1#6b06600:1 Line 3 Column 1 File C:/temp/prime_with_templates.cpp
| (template_parameter_list@Cpp~GCC5=2083#6b05460^1#6b065e0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| (template_parameter_list@Cpp~GCC5=2083#6b05140^1#6b05460:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| (template_parameter_list@Cpp~GCC5=2083#6b04ee0^1#6b05140:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| |(template_parameter_list@Cpp~GCC5=2082#6b04cc0^1#6b04ee0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | (template_parameter@Cpp~GCC5=2085#6b04ca0^1#6b04cc0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | (parameter_declaration@Cpp~GCC5=1611#6b04c80^1#6b04ca0:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04a40^1#6b04c80:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | |(decl_specifier@Cpp~GCC5=1073#6b04a20^1#6b04a40:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | | (trailing_type_specifier@Cpp~GCC5=1118#6b04a00^1#6b04a20:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp
| | | (simple_type_specifier@Cpp~GCC5=1138#6b049e0^1#6b04a00:1 Line 3 Column 10 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | | )trailing_type_specifier#6b04a00
| | |)decl_specifier#6b04a20
| | )basic_decl_specifier_seq#6b04a40
| | (ptr_declarator@Cpp~GCC5=1417#6b04c40^1#6b04c80:2 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
| | |(noptr_declarator@Cpp~GCC5=1421#6b04be0^1#6b04c40:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
| | | (declarator_id@Cpp~GCC5=1487#6b04bc0^1#6b04be0:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
| | | (id_expression@Cpp~GCC5=317#6b04b60^1#6b04bc0:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
| | | (unqualified_id@Cpp~GCC5=319#6b04ac0^1#6b04b60:1 Line 3 Column 15 File C:/temp/prime_with_templates.cpp
| | | |(IDENTIFIER@Cpp~GCC5=3368#6b049c0^1#6b04ac0:1[`no'] Line 3 Column 15 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | )unqualified_id#6b04ac0
| | | )id_expression#6b04b60
| | | )declarator_id#6b04bc0
| | |)noptr_declarator#6b04be0
| | )ptr_declarator#6b04c40
| | )parameter_declaration#6b04c80
| | )template_parameter#6b04ca0
| |)template_parameter_list#6b04cc0
| |(template_parameter@Cpp~GCC5=2085#6b04ec0^1#6b04ee0:2 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
| | (parameter_declaration@Cpp~GCC5=1611#6b04ea0^1#6b04ec0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
| | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04b40^1#6b04ea0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
| | (decl_specifier@Cpp~GCC5=1073#6b04ba0^1#6b04b40:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
| | |(trailing_type_specifier@Cpp~GCC5=1118#6b04c60^1#6b04ba0:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp
| | | (simple_type_specifier@Cpp~GCC5=1138#6b04580^1#6b04c60:1 Line 3 Column 19 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | |)trailing_type_specifier#6b04c60
| | )decl_specifier#6b04ba0
| | )basic_decl_specifier_seq#6b04b40
| | (ptr_declarator@Cpp~GCC5=1417#6b04e60^1#6b04ea0:2 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
| | (noptr_declarator@Cpp~GCC5=1421#6b04e40^1#6b04e60:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
| | |(declarator_id@Cpp~GCC5=1487#6b04de0^1#6b04e40:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
| | | (id_expression@Cpp~GCC5=317#6b04d80^1#6b04de0:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
| | | (unqualified_id@Cpp~GCC5=319#6b04ce0^1#6b04d80:1 Line 3 Column 24 File C:/temp/prime_with_templates.cpp
| | | (IDENTIFIER@Cpp~GCC5=3368#6b04560^1#6b04ce0:1[`yes'] Line 3 Column 24 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | )unqualified_id#6b04ce0
| | | )id_expression#6b04d80
| | |)declarator_id#6b04de0
| | )noptr_declarator#6b04e40
| | )ptr_declarator#6b04e60
| | )parameter_declaration#6b04ea0
| |)template_parameter#6b04ec0
| )template_parameter_list#6b04ee0
| (template_parameter@Cpp~GCC5=2085#6b05120^1#6b05140:2 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
| |(parameter_declaration@Cpp~GCC5=1611#6b05100^1#6b05120:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
| | (basic_decl_specifier_seq@Cpp~GCC5=1070#6b04d20^1#6b05100:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
| | (decl_specifier@Cpp~GCC5=1073#6b04dc0^1#6b04d20:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
| | (trailing_type_specifier@Cpp~GCC5=1118#6b04e80^1#6b04dc0:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp
| | |(simple_type_specifier@Cpp~GCC5=1140#6b046e0^1#6b04e80:1 Line 3 Column 29 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | )trailing_type_specifier#6b04e80
| | )decl_specifier#6b04dc0
| | )basic_decl_specifier_seq#6b04d20
| | (ptr_declarator@Cpp~GCC5=1417#6b05080^1#6b05100:2 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
| | (noptr_declarator@Cpp~GCC5=1421#6b05020^1#6b05080:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
| | (declarator_id@Cpp~GCC5=1487#6b05000^1#6b05020:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
| | |(id_expression@Cpp~GCC5=317#6b04fa0^1#6b05000:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
| | | (unqualified_id@Cpp~GCC5=319#6b04f00^1#6b04fa0:1 Line 3 Column 33 File C:/temp/prime_with_templates.cpp
| | | (IDENTIFIER@Cpp~GCC5=3368#6b046c0^1#6b04f00:1[`f'] Line 3 Column 33 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | | )unqualified_id#6b04f00
| | |)id_expression#6b04fa0
| | )declarator_id#6b05000
| | )noptr_declarator#6b05020
| | )ptr_declarator#6b05080
| |)parameter_declaration#6b05100
| )template_parameter#6b05120
| )template_parameter_list#6b05140
| (template_parameter@Cpp~GCC5=2085#6b05440^1#6b05460:2 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
| (parameter_declaration@Cpp~GCC5=1611#6b05420^1#6b05440:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
| |(basic_decl_specifier_seq@Cpp~GCC5=1070#6b05160^1#6b05420:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
| | (decl_specifier@Cpp~GCC5=1073#6b04fe0^1#6b05160:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
| | (trailing_type_specifier@Cpp~GCC5=1118#6b050e0^1#6b04fe0:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp
| | (simple_type_specifier@Cpp~GCC5=1140#6b050c0^1#6b050e0:1 Line 3 Column 36 File C:/temp/prime_with_templates.cpp)simple_type_specifier
| | )trailing_type_specifier#6b050e0
| | )decl_specifier#6b04fe0
| |)basic_decl_specifier_seq#6b05160
| |(ptr_declarator@Cpp~GCC5=1417#6b053e0^1#6b05420:2 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
| | (noptr_declarator@Cpp~GCC5=1421#6b053c0^1#6b053e0:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
| | (declarator_id@Cpp~GCC5=1487#6b05360^1#6b053c0:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
| | (id_expression@Cpp~GCC5=317#6b05280^1#6b05360:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
| | |(unqualified_id@Cpp~GCC5=319#6b051a0^1#6b05280:1 Line 3 Column 40 File C:/temp/prime_with_templates.cpp
| | | (IDENTIFIER@Cpp~GCC5=3368#6b046a0^1#6b051a0:1[`p'] Line 3 Column 40 File C:/temp/prime_with_templates.cpp)IDENTIFIER
| | |)unqualified_id#6b051a0
| | )id_expression#6b05280
| | )declarator_id#6b05360
| | )noptr_declarator#6b053c0
| |)ptr_declarator#6b053e0
| )parameter_declaration#6b05420
| )template_parameter#6b05440
| )template_parameter_list#6b05460
참고 URL : https://stackoverflow.com/questions/14589346/is-c-context-free-or-context-sensitive
'Programming' 카테고리의 다른 글
pip 및 요구 사항 파일을 사용하여 특정 패키지를 업그레이드하려면 어떻게해야합니까? (0) | 2020.02.22 |
---|---|
XML과 HTML을 정규식으로 구문 분석하기 어려운 이유에 대한 몇 가지 예를 제공 할 수 있습니까? (0) | 2020.02.22 |
Windows에 / dev / null이 있습니까? (0) | 2020.02.22 |
Pandas의 map, applymap 및 apply 메소드의 차이점 (0) | 2020.02.22 |
JDK 코드를 실행할 때 Java JIT가 부정 행위를합니까? (0) | 2020.02.22 |