2013-11-20 2 views
4

yacc 컴파일러에 대한 질문이 있습니다. 나는 간단한 yacc 문법을 컴파일하지 않는다. 다음은 코드 섹션입니다.간단한 yacc 문법 오류가 발생했습니다

/*anbn_0.y */ 
%token A B 
%% 
start: anbn '\n' {printf(" is in anbn_0\n"); 
return 0;} 
anbn: empty 
| A anbn B 
; 
empty: ; 
%% 
#include "lex.yy.c" 
yyerror(s) 
char *s; 
{ printf("%s, it is not in anbn_0\n", s); 

저는 Mac OS X을 사용하고 있습니다. $ yacc anbn_0.y 다음에 $ gcc -o anbn_0 y.tab.c -ll으로 잘못되었습니다. 다음은 오류입니다.

warning: implicit declaration of function 'yylex' is invalid in C99 [-Wimplicit-function-declaration] 
     yychar = YYLEX; 

왜 오류가 발생합니까?

+2

오류가 발생하지 않았습니다. 경고입니다. 거의 자명하지 않습니다. 실행중인 yacc의 버전은 최신 C99 표준이 아닌 이전 C89 표준 (또는 이전 버전)을 따르는 코드를 생성합니다. –

답변

6

경고가 아니요 오류가 아니므로 무시해도됩니다. 당신이 정말로 경고 없애 원한다면, 당신은 당신의 .y 파일 여기

+0

re-entrant 파서를 사용하고 yylex가'YYSTYPE *'매개 변수를 사용하는 경우 이는 작동하지 않습니다. 'YYSTYPE' 타입은 파일의 그 시점에서 알려지지 않습니다. 그리고 ANSI가 아닌 프로토 타입 구문을 피하면서'int yylex (void)'를 만들어야합니다. – Kaz

+0

byacc (Berkeley Yacc)를 사용하면 마지막 '%%'다음 마지막 섹션에 문법 다음에 선언을 넣을 수 있으며 모든 것이 멋지다. 생성 된 파서는 여전히 그 범위에있다. 바이슨에서는 작동하지 않습니다. – Kaz

+0

@Kaz : bison과 Berkeley yacc에서는 yylex를 사용하기 전에 골격에 yylex를 올바르게 선언 할 필요가 없습니다 (사용하는 경우 재진입 가능한 모든 관련 자료가 포함됨). 암시 적 선언을 가정하는 고대 버전의 AT & T yacc에 대한 선언 만 추가하면됩니다. –

6

의 상단에

%{ 
int yylex(); 
%} 

를 추가 할 수 있습니다 쉽게하지 않은이 문제의보다 정교한 버전에 대한 답변입니다 선언을 추가하여 해결했습니다.

GNU Bison은 Flex와 함께 작동하는 재진입 파서 생성을 지원합니다 (Flex의 %option bison-bridge re-entrant 사용). Berkeley Yacc는 호환 가능한 구현을 제공합니다.

다음은이 두 가지 파서 생성기에 대해 선언되지 않은 yylex을 해결하는 방법에 대한 가이드입니다. 재 참가자와

, 렉서는, yylex의 선언이로 변신 "들소는 브리지"

int yylex(YYSTYPE *yylval, void *scanner); 

당신이 당신의 Yacc에 파서의 %{ ... %} 초기 헤더 섹션에서이 프로토 타입을 놓고가 발생하는 경우 Bison 또는 Berkeley Yacc와 파서를 컴파일하면 컴파일러에서 YYSTYPE이 선언되지 않는다고 불평 할 것입니다.

YYSTYPE에 대한 전달 선언을 만들 수는 없습니다. 버클리 Yacc에서는 유니온 태그가 없기 때문입니다. Bison에서는 typedef union YYSTYPE { ... } YYSTYPE이지만 Berkeley Yacc에서는 typedef { ... } YYSTYPE : 태그가 없습니다.

하지만 Berkeley Yacc에서는 파서의 세 번째 섹션에 선언을 넣으면이 호출의 범위가 입니다! 버클리 Yacc에 대해 다음 작품 그래서 :이 들소와 함께 발생하면

%{ 
/* includes, C defs */ 
%} 

/* Yacc defs */ 

%% 

/* Yacc grammar */ 

%% 

int yylex(YYSTYPE *, void *); 

/* code */ 

, 문제가 계속 다음 yylex 전화의 범위에는 프로토 타입이 없다.

이 작은 수정은 GNU 들소 작동한다 :이

%{ 
/* includes, C defs */ 

#if YYBISON 
union YYSTYPE; 
int yylex(union YYSTYPE *, void *); 
#endif 

%} 

/* Yacc defs */ 

%% 

/* Yacc grammar */ 

%% 

int yylex(YYSTYPE *, void *); 

/* code */ 

당신이 이동합니다.

관련 문제