LR 파서는 모호한 문법 규칙을 의도적으로 처리 할 수 없습니다. (아이디어가 진행되고 있던 1970 년대에 이론을 더 쉽게 만들었습니다.)
C와 C ++ 모두 다음 문장을 허용합니다.
x * y ;
두 가지 다른 구문 분석이 있습니다.
- x를 가리키는 포인터로 y를 선언 할 수 있습니다.
- x와 y를 곱하여 답을 버릴 수 있습니다.
이제 후자가 어리 석고 무시해야한다고 생각할 수도 있습니다. 대부분은 당신에게 동의 할 것입니다. 그러나 부작용이있을 수있는 경우가 있습니다 (예 : 곱하기에 과부하가 걸리는 경우). 그러나 그것은 요점이 아닙니다. 포인트가 있는 두 개의 서로 다른 파싱이 때문에 프로그램이이 방법에 따라 다른 것을 의미 할 수 있어야 구문 분석되고있다.
컴파일러는 적절한 환경에서 적절한 정보를 수용해야하며, 다른 정보가없는 경우 (예 : x 유형에 대한 지식) 나중에 수행 할 작업을 결정하기 위해 둘 다 수집해야합니다. 따라서 문법은 이것을 허용해야합니다. 그리고 그것은 문법을 모호하게 만듭니다.
따라서 순수한 LR 구문 분석은이를 처리 할 수 없습니다. Antlr, JavaCC, YACC 또는 전통적인 Bison과 같은 널리 사용되는 다른 파서 생성기 나 "순수한"방식으로 사용되는 PEG 스타일 파서도 사용할 수 없습니다.
더 복잡한 경우가 많이 있습니다 (템플릿 구문 분석에는 임의의 미리보기가 필요하지만 LALR (k)는 대부분의 k 토큰을 미리 볼 수 있음). 순수한 LR (또는 다른) 구문 분석을 처리하는 데에는 반례가 하나만 필요 합니다.
대부분의 실제 C / C ++ 파서는 추가 해킹과 함께 일종의 결정 론적 파서를 사용 하여이 예제를 처리합니다. 심볼 테이블 컬렉션과 파싱을 얽어 묶습니다 ... "x"가 발생하면 파서는 x가 유형인지 알 수 있습니다. 또는 두 개의 잠재적 구문 분석 중에서 선택할 수 있습니다. 그러나이 작업을 수행하는 파서는 컨텍스트가 없으며 LR 파서 (순수한 것 등)에는 컨텍스트가 없습니다.
이러한 명확성을 위해 LR 파서에서 규칙 당 축소 시간 의미 검사를 속이고 추가 할 수 있습니다. (이 코드는 종종 단순하지 않습니다). 대부분의 다른 파서 유형에는 구문 분석의 다양한 지점에서 의미 검사를 추가 할 수있는 수단이 있습니다.
충분히 속임수를 쓰면 LR 파서를 C와 C ++에서 사용할 수 있습니다. GCC 직원은 잠시 동안 수행했지만 수동 코딩 파싱을 포기했습니다. 더 나은 오류 진단을 원했기 때문입니다.
그러나 또 다른 접근 방법이 있습니다.이 방법은 훌륭하고 깨끗하며 기호 테이블 해커가없는 C 및 C ++을 잘 구문 분석합니다 .GLR parsers . 이들은 컨텍스트가없는 완전한 파서입니다 (효과적으로 무한한 예측을 가짐). GLR 파서는 단순히 두 구문 분석을 모두 받아 들여 모호한 구문 분석을 나타내는 "트리"(실제로 나무와 같은 방향이 지정된 비순환 그래프)를 생성합니다. 구문 분석 후 패스로 모호성을 해결할 수 있습니다.
우리는이 기술을 DMS 소프트웨어 리엔지니어링 Tookit의 C 및 C ++ 프론트 엔드에서 사용합니다 (2017 년 6 월 현재 MS 및 GNU 방언에서 전체 C ++ 17을 처리합니다). 수백만 줄의 대형 C 및 C ++ 시스템을 처리하는 데 사용되었으며, 소스 코드에 대한 완전한 세부 사항으로 AST를 생성하는 완전하고 정밀한 구문 분석 기능이 있습니다. ( C ++에서 가장 까다로운 구문 분석에 대해서는 AST를 참조하십시오 . )