%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 :
가
C 문자열에서 토큰 이름의 직접적인 사용은 그 표현 "
또는 \
를 포함하는 토큰의 경우에는 작동하지 않을 것이다. 특히 단일 문자 토큰 '"'
및 '\\'
처럼 어떤 키워드 토큰 ("and"
또는 "<="
)도 실패합니다. 이들은 문법에 매우 자주 나타나지 않습니다. 스캐너로 국제화 된 키워드를 대체한다면 바이슨의 인용 문자열 기능을 전혀 사용하지 않을 것입니다.
이러한 토큰을 사용하려면 토큰 이름에 "
및 \
자를 이스케이프 처리하는 gettext 생성기에 대한 코드를 출력해야합니다.
실제로 여러 스탠자를 사용하는 것이 좋지만 그 중 하나를 사용하면 충분합니다. 중간 결과 중 일부 또는 전부를 .INTERMEDIATE
으로 표시하려고합니다. 생성 된 실행 파일 my_parser.tokens
은 번역을 확인하는 데 사용할 수 있지만 이는 전적으로 선택 사항이므로 해당 행을 제거 할 수 있습니다. 반면에 문자열이 컴파일 가능한지 확인합니다.
예를 들어 Russ Cox의 gc
(위의 링크 참조)을 참조하십시오. 그의 Makefile은 const
을 yytname
에서 제거하기 위해 bison 출력을 수정하므로 생성 된 파서가 오류 메시지에 대한 선호 토큰 이름을 대체 할 수 있으므로 작업시 일반적인 생각을 볼 수 있습니다.
답장을 보내 주셔서 감사합니다. 불행히도 자동으로 번역 할 문자열을 추출 할 수 없기 때문에'% token-table'만큼 충분하지 않습니다. 다른 사람이 읽을 수있는 토큰 이름을 사용하여 다른 사람의 언어에 대한 사람이 읽을 수있는 문법 설명을 이미 가지고 있습니다. 그리고 인간이 읽을 수있는 토큰 이름을 사용하여 오류 메시지를 출력하려고합니다. 또한 각 예약어는 영어와 독일어의 두 가지 맛이 있습니다. 지금까지는 스캐너에 의해 관리됩니다. 따라서 무조건 단일 언어의 키워드 만 사용할 수는 없습니다. – Keinstein
@keinstein : yytname이 스캐너에만있는 경우 키워드를 찾을 수 없습니다. yytnamerr의 유일한 목적은 yytname의 이름을 최종 사용자에게 표시 할 수 있도록 만들어 번역하는 것입니다. – rici
키워드는 지금까지 번역되지 않은 문제를 제외하고는 표시 할 수 있습니다. 또 다른 문제가 있습니다. gettext는'yytname'에있는 키워드에 대해 알지 못합니다. 그래서 그것을 추출 할 수 없습니다. 어떻게 자동 추출 할 수 있습니까? – Keinstein