2017-10-01 8 views
0

렉서 단계에서 기호 표를 작성해야하는 이유가 있습니까?기호 표 작성에 적합한 단계

flex & bison: Text Processing Tools 책에서 저자는 간단한 기호 테이블을 작성하려는 시도로 렉서의 예를 제시합니다.

/* declaration keywords */ 
auto | 
char | 
int | 
/* ... skip ... */ 
volatile { defining = 1; } 

/* ... skip ... */ 

/* punctuators */ 
"{"|"<%"|";" 
{ defining = 0; } 

이 솔루션은 더 복잡한 경우에서 작동하지 않습니다 같은 int a = b, c = d; (기호 c이 정의로 표시되지 않습니다)의 참조에서 기호 정의를 구별하는 다음 코드에서 해결 방법이있다. 이 외에도 중첩 된 범위는 렉서 단계에서 처리 할 수 ​​없습니다.

질문에서 lex and yacc (symbol table generation) lexer의 기호 테이블 액세스는 일반적인 것이지만 나는 여전히 프로가 보이지 않으며 왜 나중에 lexer에 내장 된 테이블이 유용할지 알 수 있습니다.

답변

1

한 가지 이유는 메모리 관리입니다. 렉서에서 파서 (적어도 식별자 토큰의 경우)로 전달되는 토큰 문자열의 복사본을 만드는 것이 일반적이지만 식별자는 일반적으로 소스 텍스트에 두 번 이상 나타나며 실제로는 하나의 복사본 만 필요합니다.

매번 복사본을 수행하는 대신 식별자의 해시 테이블에서 문자열을 "인턴드"하고 해시 테이블 항목을 전달하는 것이 편리 할 수 ​​있습니다. 이렇게하면 각 심볼의 두 번째 및 이후 모양이 동적 할당을 초래하지 않습니다. 또한 전체 문자열 저장소를 문자열 테이블 데이터 구조의 일부로 유지할 수 있으므로 동적으로 할당 된 저장소를 해제하는 논리를 단순화 할 수 있습니다.

의미 테이블이나 범위 정보를 아직 (아직) 보유하지 않으므로 정확히 기호 테이블이 아닙니다. 그러나 문자열 테이블은 적어도 "기호 테이블을 만드는 시작"으로 충분할만큼 심볼 테이블을 보유하는 기본 구조 일 수 있습니다.

특정 언어 (C가 표준 예)에서 렉서는 기호 테이블의 의미 정보를 참조 할 수 있기를 원하므로 공유가 더 얽힐 수 있습니다. 그러나 그러한 해커가 없어도 기본적인 색인 메커니즘을 공유하는 것이 유용 할 수 있으며, 반드시 관심사 분리의 개념을 깨뜨리는 것은 아닙니다.

+0

매우 분명한 동기이지만 한 가지 질문이 남아 있습니다. 왜 '정의'플래그를 렉서 규칙에 넣어야합니까? 저자의 예는 극히 간단하며이 해결 방법은 일을 끝내기에 충분합니다. – Unforgiven

+3

@unforgiven : 스 니펫은 flex 만 사용하여 작성된 예제 도구에서 가져온 것입니다. 이 도구는 심볼의 정의와 심볼 사용을 상호 참조하려고 시도합니다. 소스 텍스트를 실제로 파싱하지 않기 때문에 주어진 식별자 사용이 정의인지 또는 사용인지를 결정하기위한 어휘 힌트에 의존합니다. 그 내용은 본문에서 설명되어 있습니다. – rici