[java] C보다 Java를 구문 분석하기가 더 쉬운 이유는 무엇입니까?
저는 C와 C ++의 문법이 문맥에 민감 하다는 사실을 잘 알고 있습니다. 특히 C에서 “lexer hack”이 필요하다는 사실을 알고 있습니다. 두 언어간에 상당한 유사성에도 불구하고 2 개의 미리보기 토큰.
구문 분석을 더 쉽게하기 위해 C에 대해 무엇을 변경해야합니까?
C의 컨텍스트 민감도에 대해 본 모든 예제가 기술적으로 허용되지만 끔찍하게 이상하기 때문에 묻습니다. 예를 들면
foo (a);
foo
인수로 void 함수 를 호출 할 수 있습니다 a
. 또는 a
유형의 객체 로 선언 할 수 foo
있지만 괄호를 쉽게 제거 할 수 있습니다. 부분적으로 이러한 이상 함은 C 문법에 대한 “직접 선언자”생성 규칙이 함수와 변수를 모두 선언하는 이중 목적을 충족 하기 때문에 발생 합니다.
반면에 Java 문법 에는 변수 선언과 함수 선언에 대한 별도의 생산 규칙이 있습니다. 당신이 쓰면
foo a;
그러면 그것이 변수 선언이고 foo
분명하게 타입 이름으로 파싱 될 수 있다는 것을 알고 있습니다. 클래스 foo
가 현재 범위의 어딘가에 정의되지 않은 경우 유효한 코드가 아닐 수 있지만 이는 나중에 컴파일러 패스에서 수행 할 수있는 의미 분석 작업입니다.
C가 typedef로 인해 구문 분석하기 어렵다고 말했지만 Java에서도 자신의 유형을 선언 할 수 있습니다. 외에 어떤 C 문법 규칙 direct_declarator
이 잘못 되었습니까?
답변
C ++ 구문 분석이 어려워지고 있습니다. 자바 구문 분석도 그만큼 어려워지고 있습니다.
C (및 C ++)가 구문 분석하기 “어려운”이유를 설명하는 이 SO 답변을 참조하십시오 . 짧은 요약은 C 및 C ++ 문법 이 본질적으로 모호하다는 것입니다. 여러 구문 분석을 제공 하므로 모호성을 해결하려면 컨텍스트를 사용해야합니다 . 그런 다음 사람들은 구문 분석 할 때 모호성을 해결해야한다고 가정하는 실수를합니다. 그렇지 않으면 아래를 참조하십시오. 구문 분석 할 때 모호성을 해결해야한다고 주장하면 구문 분석기가 더 복잡해지고 빌드하기가 훨씬 더 어려워집니다. 하지만 그 복잡성은 자해 상처입니다.
IIRC, Java 1.4의 “명백한”LALR (1) 문법은 모호하지 않았으므로 구문 분석이 “쉬웠습니다”. 나는 현대 자바가 적어도 장거리 로컬 모호성을 가지고 있지 않다고 확신하지 못한다. “… >>”가 두 개의 템플릿을 닫는 지 또는 “오른쪽 시프트 연산자”인지 여부를 결정하는 데 항상 문제가 있습니다. 현대 자바가 더 이상 LALR (1)로 구문 분석하지 않는다고 생각 합니다.
그러나 두 언어 모두에 대해 강력한 파서 (또는 현재 C 및 C ++ 프런트 엔드가 대부분 사용하는 약한 파서 및 컨텍스트 수집 해킹)를 사용하여 파싱 문제를 해결할 수 있습니다. C와 C ++는 전처리기를 갖는 추가적인 복잡성이 있습니다. 이들은보기보다 실제로 더 복잡합니다. 한 가지 주장은 C 및 C ++ 파서가 너무 어렵 기 때문에 손으로 작성해야한다는 것입니다. 사실이 아닙니다. GLR 파서 생성기를 사용하면 Java 및 C ++ 파서를 빌드 할 수 있습니다.
그러나 파싱은 실제로 문제가있는 곳이 아닙니다.
구문 분석을 마치면 AST / parse 트리를 사용하여 작업을 수행 할 수 있습니다. 실제로 모든 식별자에 대해 그 정의가 무엇이며 어디에 사용되는지 알아야합니다 ( “이름 및 유형 확인”, 엉성하게 기호 테이블 작성). 이것은 상속, 인터페이스, 오버로딩 및 템플릿으로 인해 구문 분석기를 올바르게 설정하는 것보다 훨씬 더 많은 작업이며,이 모든 것에 대한 의미 체계가 수십에서 수백 페이지에 걸쳐있는 비공식적 인 자연 언어로 작성되었다는 사실로 인해 혼란스러워졌습니다. 언어 표준의. 여기서 C ++는 정말 나쁩니다. Java 7과 8은이 관점에서 꽤 끔찍해졌습니다. (심볼 테이블이 필요한 전부는 아닙니다. “파싱 이후의 삶”에 대한 더 긴 에세이는 저의 약력을 참조하십시오).
대부분의 사람들은 순수한 구문 분석 부분 (종종 절대 끝나지 않습니다. 실제 언어에 대한 작동 구문 분석기를 빌드하는 방법에 대한 많은 질문에 대해 SO 자체를 확인하십시오)에 어려움을 겪으므로 구문 분석 후 삶을 보지 못합니다. 그리고 우리는 파싱하기 어려운 것에 대한 민속 정리를 얻고 그 단계 이후에 일어나는 일에 대한 신호가 없습니다.
C ++ 구문을 수정해도 아무데도 가지 않습니다.
C ++ 구문 변경과 관련하여 : 모든 C ++ 문법에서 다양한 로컬 및 실제 모호성을 처리하기 위해 많은 부분을 패치해야합니다. 주장한다면 다음 목록이 좋은 출발점이 될 수 있습니다 . 나는 당신이 C ++ 표준위원회가 아니라면이 일을하는 데 아무런 의미가 없다고 주장한다. 당신이 그렇게하고 그것을 사용하여 컴파일러를 구축한다면, 아무도 그것을 사용하지 않을 것입니다. 파서를 구축하는 사람들의 편의를 위해 전환하기 위해 기존 C ++ 애플리케이션에 너무 많은 투자가 이루어졌습니다. 게다가 그들의 고통은 끝났고 기존 파서는 잘 작동합니다.
자신의 파서를 작성하는 것이 좋습니다. 좋아요, 괜찮습니다. 커뮤니티의 나머지 부분이 여러분이 더 쉽게 사용할 수 있도록 사용해야하는 언어를 변경할 수 있다고 기대하지 마십시오. 그들은 모두 그들이 더 쉽게하기를 원하며 그것은 문서화되고 구현 된대로 언어를 사용하는 것입니다.