2012-10-14 3 views
0

자산 xchange 형식의 구문 분석기를 작성하고 있습니다. 그리고 필자는 bison 파일에 % token-table 지시어를 포함하고 있지만 플렉스 코드에서는 테이블이나 그와 관련된 상수에 액세스 할 수 없습니다.바이슨 2.6에서 토큰 테이블 yytname에 액세스 할 수 없거나 사라 졌습니까?

Frame|FrameTransformMatrix|Mesh|MeshNormals|MeshMaterialList|Material { 
    printf("A keyword: %s\n", yytext); 
    yylval.charptr_type = yytext; 

    int i; 
    for (i = 0; i < YYNTOKENS; i++) 
    { 
     if (yytname[i] != 0 
      && yytname[i][0] == '"' 
      && !strncmp(yytname[i] + 1, yytext, strlen(yytext)) 
      && yytname[i][strlen(yytext) + 1] == '"' 
      && yytname[i][strlen(yytext) + 2] == 0) 
      return i; 
    } 
} 

GCC는 YYNTOKENS 및 yytname 모두가 선언되지 않은 말합니다 :이 코드를 컴파일 할 때 때문입니다. 그래서 토큰 테이블이 마침내 사용 중지되고 삭제되었거나 거래가 무엇입니까?

답변

0

들소 2.6.2 설명서 (PDF에 P82에) 말한다 :

%token-table [지침]

파서 구현 파일의 토큰 이름의 배열을 생성합니다. 배열의 이름은 yytname입니다. 은 내부 Bison 토큰 의 코드 번호가 i 인 토큰의 이름입니다. yytname의 처음 세 요소는 사전 정의 된 토큰 " $end", " error"및 " $undefined"에 해당합니다. 이 후에는 에 정의 된 기호가 문법 파일에옵니다.

표의 이름은 Bison의 토큰을 나타내는 데 필요한 모든 문자를 포함합니다. 단일 문자 리터럴 및 리터럴 문자열의 경우 주변 문자 및 모든 이스케이프 시퀀스가 ​​포함됩니다. 예를 들어, Bison 단일 문자 리터럴 ’+’은 C에서 "’+’"으로 표시되는 3 문자 이름에 해당합니다. 바이손의 2 문자 리터럴 문자열 은 5 문자 이름에 해당하며 은 "\"\\\\/\""으로 표시됩니다.

YYNTOKENS 가장 높은 토큰 번호, 더하기 하나 : 당신이 % 토큰 테이블을 지정

는 들소는 매크로 YYNTOKENS, YYNNTSYYNRULESYYNSTATES 매크로 정의를 생성합니다.

YYNNTS 비 터미널 기호의 수.

YYNRULES 문법 규칙의 개수,

YYNSTATES 파서 상태 (섹션 5.5 파서 미국], 104 페이지 참조)의 수.

거기에있는 것처럼 보입니다. 나는 사소한 문법을 ​​시도했을 때

는, 테이블이 존재 :

#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE 
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. 
    First, the terminals, then, starting at YYNTOKENS, nonterminals. */ 
static const char *const yytname[] = 
{ 
    "$end", "error", "$undefined", "ABSINTHE", "NESTLING", "$accept", 
    "anything", 0 
}; 
#endif 

주 : 테이블이 정적; 파일 외부에서 액세스하려고하면 작동하지 않습니다.

/* Enabling the token table. */ 
#ifndef YYTOKEN_TABLE 
# define YYTOKEN_TABLE 1 
#endif 

이 토큰 테이블이 정의되는 것을 보장 :

은 소스에 이전 스 D 자에 있습니다.

+0

정적이라면 렉서 코드가 생성 된 Bison 코드 안에 있어야 할 필요가 있습니까? ... 필자는 Bison과 Flex를 함께 사용할 수 있다고 말합니다. 그러나 그것을 사용하는 일반적인 방법은 bison에 헤더를 생성하고 플렉스 생성기 파일에 헤더를 포함시키는 것입니다. – SaldaVonSchwartz

+0

내가 틀렸다고 정정하십시오. 그렇다면 flex와 bison 파일을 분리하여 gcc를 통해 링크하면 나중에 generic 키워드 토큰을 반환하고 flex 코드에서 yylval을 설정 한 다음 bison에서 일반 제작을 만들어야합니다 일반적인 키워드가있는 경우 yyval을 검색하여 무슨 일이 일어나는지 확인할 수 있습니까? 테이블에 직접 접근하는 유일한 방법은 렉서 코드가 bison 파일 안에 있다면? – SaldaVonSchwartz

+0

그리고 예, btw, 당신 말이 맞아요. 내가 % token-table로 전환하기 전에 잘못된 파일 (.tab.c)을 확인하고있었습니다. 하지만 여전히 .. 나는 테이블 옵션이 플렉스와 함께 사용되도록 의도되었다는 것을 문서에서 알았을 것 같다. – SaldaVonSchwartz

0

'정적'문제를 해결하는 빠르고 쉬운 방법이 있습니다. 내 C에서 6502 컴파일러에 대한 각 비 터미널의 문자열 표현을 사용하여 사람이 읽을 수있는 추상 구문 트리를 인쇄하려고했습니다. 여기

마지막 섹션에서 .Y 파일에서

, token_table하는 yytname을 할당하여 yyparse 호출하는 주요 방법,

%% 
#include <stdio.h> 

extern char yytext[]; 
extern int column; 
const char ** token_table; 
... 

이제 token_table라는 비 정적 변수를 만들 ... 내가 무슨 짓을했는지 이제

int main(int argc, char ** argv) { 
    FILE * myfile; 
    yydebug = 1; 
    token_table = yytname; 
    ... 

, 당신은 같이 단순히 통근로 선언하여 모든 컴파일 단위에서 token_table에 액세스 할 수 있습니다

extern const char ** token_table; 

/* Using it later in that same compilation unit */ 
printf("%s", token_table[DOWHILE - 258 + 3]); /* prints "DOWHILE" */ 

AST의 각 노드에 y.tab.h에있는 yytokentype 값을 할당하면 258을 빼고 token_table (yytname)에 3을 더하면됩니다. yytokentype이 열거되기 시작하는 곳에서 258 b/c를 빼고 3 b/c를 추가해야합니다. yytname은 처음에 세 개의 예약 기호 ("$ end", "error"및 "$ undefined")를 추가합니다. 탁자. 합니다 (--defines = y.tab.h 옵션을 실행 들소)의 정의 헤더를

static const char *const yytname[] = 
{ 
    "$end", "error", "$undefined", "DOWHILE", "UAND", "UMULT", "UPLUS", 
    "UMINUS", "UBANG", "UTILDE", "ARR", "NOOP", "MEMBER", "POSTINC", 
    ... 

을 그리고 :

예를 들어, 내 생성 들소 파일이

/* Tokens. */ 
#ifndef YYTOKENTYPE 
# define YYTOKENTYPE 
    /* Put the tokens into the symbol table, so that GDB and other debuggers 
     know about them. */ 
    enum yytokentype { 
    DOWHILE = 258, 
    UAND = 259, 
    UMULT = 260, 
    ... 
0

정적 기호 문제를 피하는 가장 쉬운 방법은 들소 입력 파일의 세 번째 섹션에 직접 렉서 인 #include입니다.

/* token declarations and such */ 
%% 
/* grammar rules */ 
%% 

#include "lex.yy.c" 

int main() { 
    /* the main routine that calls yyparse */ 
} 

그런 다음 .tab.c 파일을 컴파일하기 만하면됩니다.

관련 문제