필자는 컴파일러의 기본 원리, 기술 및 도구 (제 2 판) ( 제 2 판)의 여러 문서, 기사 및 4.1.4 절 (제 2 판) (일명 "드래곤 북 (Dragon Book)")을 읽었으며 구문 컴파일러 오류 복구 주제에 대해 설명했다. 그러나 현대의 여러 컴파일러를 실험 한 결과 시맨틱 오류뿐만 아니라 구문 오류 도 복구 합니다.
문법적으로 관련된 오류를 복구하는 컴파일러의 알고리즘과 기술을 상당히 잘 이해하고 있지만 컴파일러가 의미 론적 오류를 복구하는 방법을 정확하게 이해하지 못합니다.
저는 현재 추상 구문 트리에서 코드를 생성하기 위해 약간의 방문자 패턴을 사용하고 있습니다. 컴파일러가 다음 표현식을 컴파일하는 것을 고려하십시오.
1 / (2 * (3 + "4"))
컴파일러는 다음과 같은 추상 구문 트리를 생성합니다.
op(/)
|
-------
/ \
int(1) op(*)
|
-------
/ \
int(2) op(+)
|
-------
/ \
int(3) str(4)
그런 다음 코드 생성 단계에서는 방문자 패턴을 사용하여 추상 구문 트리를 재귀 적으로 탐색하고 유형 검사를 수행합니다. 컴파일러가 표현식의 가장 안쪽에 올 때까지 추상 구문 트리가 순회됩니다. (3 + "4")
. 그런 다음 컴파일러는 표현식의 각 측면을 확인하고 의미 상 동등하지 않은 것을 확인합니다. 컴파일러에서 형식 오류가 발생합니다. 여기에 문제가 있습니다. 이제 컴파일러는 무엇을해야합니까 ?
컴파일러가이 오류를 복구하고 표현식의 외부 부분을 계속 유형 검사하려면 표현식 의 가장 안쪽 부분을 평가하여 표현식의 다음 가장 안쪽 부분으로 일부 유형 ( int
또는 str
) 을 리턴해야합니다 . 그러나 단순히 반환 할 유형이 없습니다 . 타입 에러가 발생했기 때문에 타입이 추론되지 않았습니다.
내가 가정 한 한 가지 가능한 해결책은 유형 오류가 발생하면 오류가 발생하고 유형 오류가 발생했음을 나타내는 특수 값이 이전 추상 구문 트리 탐색 호출로 반환되어야한다는 것입니다. 이전 순회 호출에이 값이 있으면 추상 구문 트리에서 유형 오류가 더 많이 발생했음을 알고 유형을 추론하려고 시도하지 않아야합니다. 이 방법은 효과가있는 것처럼 보이지만 매우 비효율적 인 것 같습니다. 표현식의 가장 안쪽 부분이 추상 구문 트리에 깊은 경우 컴파일러는 실제 작업을 수행 할 수 없다는 것을 깨닫기 위해 많은 재귀 호출을 수행해야하며 각 작업에서 간단히 반환해야합니다.
위에서 설명한 방법이 사용 되었습니까? 그렇다면 효율적이지 않습니까? 그렇지 않은 경우 컴파일러가 의미 적 오류에서 복구 할 때 사용되는 방법은 정확히 무엇입니까?