2013-08-31 5 views
1

나는 내 목적을 위해 충분히 잘 작동하는 바이슨 파서를 가지고있다. 심지어는 지역화 된 오류 메시지를 인쇄합니다. 그러나 토큰 이름은 변환되지 않습니다. 내가 찾은 소스 코드를보고, 내 자신의 gettext 함수에 YY_을 정의하고 오류 메시지를 직접 번역하기 위해 gettext에 YY_을 전달할 수있다. 그러나 이것은 토큰 이름에 대해서는 작동하지 않습니다.들소에서 토큰 이름을 변환하는 방법

파서에서 토큰 이름을 추출하고 번역하기 위해 사용할 수있는 스위치 또는 숨겨진 기능이 있습니까?

지금까지 토큰 이름의 형식을 재정의 할 수있는 yytnamerr을 발견했습니다. 이름을 다시 포맷하는 것 이상으로이 기능을 만지기를 좋아하지 않습니다. 필자는이 기능을 Bison의 진행 상황과 동기화해야하므로 반면에 파서에서 토큰 이름을 추출하여 언어 정의 파일에 토큰 이름을 추가하는 방법이 필요합니다.

어떻게 Bison과 사용자 친화적 인 오류보고를 구현합니까?

답변

0

%token-table을 지정하면 bison은 yytname 테이블을 생성합니다. 이 테이블에는 내부 기호 ($end, $error$undefined), 터미널 이름이 지정된 작은 따옴표가 붙은 문자열 및 큰 따옴표가 붙은 문자열을 비롯하여 모든 비손 기호가 포함되며 비 중간 터미널에는 생성 된 중간 규칙 작업의 이름이 포함됩니다 .

yytname이 표시되면 gettext 패키지에서 인식 할 수있는 형식으로 토큰을 쉽게 추출 할 수 있습니다.

#ifdef MAKE_TOKEN 
int main(void) { 
    puts("#include <libintl.h>"); 
    puts("#include <stdio.h>"); 
    puts("int main() {"); 
    for (const char* const* p = yytname; *p; ++p) { 
    // See Note 1 below 
    printf(" printf(\"%%s: %%s\\n\", \"%s\", gettext (\"%s\"));\n", *p, *p); 
    } 
    puts("}"); 
} 
#endif 

를 다음 (파일 이름을 만드는 적절한 대체) 귀하의 메이크에 연을 추가합니다 : 예를 들어, 당신은이처럼 .y 파일 무언가에 추가 할 수

messages.pot: my_parser.c 
    $(CC) $(CFLAGS) -DMAKE_TOKEN -o token_lister $< 
    ./token_lister > my_parser.tokens.c 
    # See Note 2 below 
    $(CC) -o my_parser.tokens my_parser.tokens.c 
    xgettext -o [email protected] my_parser.tokens.c 

당신이 번역이되면 bison은 변환 된 토큰 이름을 생성 된 오류 메시지에 삽입하기위한 인터페이스를 제공하지 않기 때문에 여전히 이들을 사용하는 방법을 알아야합니다. 아마도 가장 간단한 방법은 해당 배열을 반복하여 각 토큰 이름을 해당 변환 (파서 시작시 완료되어야 함)으로 대체하여 번역을 yytname에 직접 삽입하는 것입니다. 그것은 yytname가 들소 해골에 의해 const 선언되는 성가심을 선물한다; 그러나 매우 간단한 sed 또는 awk 호출을 사용하여 문제가되는 const을 제거 할 수 있습니다. [주 3]

그런데, 자동으로 생성 된 오류 메시지는 사용자가 놀랍게도 언어의 공식적인 문법에 익숙하지 않다면 나에게 분명하지 않습니다. 그리고 문법에 익숙한 사용자는 원래의 개념과 우연히 닮은 비 전문가 번역이 아닌 원래의 토큰 이름을 문법에서 찾기 위해 선호합니다. 내가 특별히 손가락을 가리키고있는 것은 아닙니다.

러스 콕스 (Russ Cox)가 Go에 대해 실제로 친숙한 오류 메시지를 구현 한 방법에 대해이 fascinating essay을 즐기실 수 있습니다.


NOTES :

  1. C 문자열에서 토큰 이름의 직접적인 사용은 그 표현 " 또는 \를 포함하는 토큰의 경우에는 작동하지 않을 것이다. 특히 단일 문자 토큰 '"''\\'처럼 어떤 키워드 토큰 ("and" 또는 "<=")도 실패합니다. 이들은 문법에 매우 자주 나타나지 않습니다. 스캐너로 국제화 된 키워드를 대체한다면 바이슨의 인용 문자열 기능을 전혀 사용하지 않을 것입니다.

    이러한 토큰을 사용하려면 토큰 이름에 "\자를 이스케이프 처리하는 gettext 생성기에 대한 코드를 출력해야합니다.

  2. 실제로 여러 스탠자를 사용하는 것이 좋지만 그 중 하나를 사용하면 충분합니다. 중간 결과 중 일부 또는 전부를 .INTERMEDIATE으로 표시하려고합니다. 생성 된 실행 파일 my_parser.tokens은 번역을 확인하는 데 사용할 수 있지만 이는 전적으로 선택 사항이므로 해당 행을 제거 할 수 있습니다. 반면에 문자열이 컴파일 가능한지 확인합니다.

  3. 예를 들어 Russ Cox의 gc (위의 링크 참조)을 참조하십시오. 그의 Makefile은 constyytname에서 제거하기 위해 bison 출력을 수정하므로 생성 된 파서가 오류 메시지에 대한 선호 토큰 이름을 대체 할 수 있으므로 작업시 일반적인 생각을 볼 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 불행히도 자동으로 번역 할 문자열을 추출 할 수 없기 때문에'% token-table'만큼 충분하지 않습니다. 다른 사람이 읽을 수있는 토큰 이름을 사용하여 다른 사람의 언어에 대한 사람이 읽을 수있는 문법 설명을 이미 가지고 있습니다. 그리고 인간이 읽을 수있는 토큰 이름을 사용하여 오류 메시지를 출력하려고합니다. 또한 각 예약어는 영어와 독일어의 두 가지 맛이 있습니다. 지금까지는 스캐너에 의해 관리됩니다. 따라서 무조건 단일 언어의 키워드 만 사용할 수는 없습니다. – Keinstein

+0

@keinstein : yytname이 스캐너에만있는 경우 키워드를 찾을 수 없습니다. yytnamerr의 유일한 목적은 yytname의 이름을 최종 사용자에게 표시 할 수 있도록 만들어 번역하는 것입니다. – rici

+0

키워드는 지금까지 번역되지 않은 문제를 제외하고는 표시 할 수 있습니다. 또 다른 문제가 있습니다. gettext는'yytname'에있는 키워드에 대해 알지 못합니다. 그래서 그것을 추출 할 수 없습니다. 어떻게 자동 추출 할 수 있습니까? – Keinstein

관련 문제