2013-12-20 4 views
5

(재진입) Flex + 레몬을 구문 분석에 사용하는 데 문제가 있습니다. 나는 간단한 문법과 렉서를 사용하고있다. here. 내가 그것을 실행할 때, 나는 EOF 토큰 (Ctrl-D)이 뒤 따르는 숫자를 넣을 것이다. 인쇄물을 읽을 :레몬 파서 0 토큰 구문 분석

89 

found int of . 
AST=0. 

을 첫 번째 줄은 내가 넣어 수가 인 경우 이론적으로 AST 값이 내가 넣어 모든 것의 합해야

편집 :.. 내가 구문 분석을 호출 할 때 () 수동으로 올바르게 실행됩니다.

또한 레몬은 토큰이 0 (정지 토큰) 인 경우에도 atom ::= INT 규칙을 실행하는 것처럼 보입니다. 왜 이런거야? 이 동작에 대해 매우 혼란스럽고 좋은 문서를 찾을 수 없습니다.

답변

5

좋아요, 알아 냈습니다. 그 이유는 플렉스와 레몬 사이에서 특히 불쾌한 (그리고 잘 설명되지 않은) 상호 작용이 일어나기 때문입니다.

메모리를 절약하기 위해 레몬은 복사하지 않고 토큰을 잡고 내부 토큰 스택으로 밀어 넣습니다. 그러나 flex는 입력을 렉스 때문에 yyget_text이 가리키는 값을 변경하여 메모리를 절약하려고합니다. 내 예에서 문제가되는 라인은 다음과 같습니다

// in the do loop of main.c... 
Parse(parser, token, yyget_text(lexer)); 

이 있어야한다 :

Parse(parser, token, strdup(yyget_text(lexer))); 

보장되는 그 값이 무엇을 원래와 동일 토큰 스택 이후 감소 인 경우에 그 레몬 포인트 전달됨

(참고 : strdup은 나중에 어느 시점에서 그 메모리를 해제해야한다는 것을 의미합니다.) 레몬은이를 수행 할 수있는 토큰 "소멸자"를 작성하게하거나 작성중인 경우 AST 수명이 끝날 때까지 기다려야하는 AST 트리입니다.)

0

문자열 길이가 이고 인 토큰 유형을 만들 수도 있습니다. 나는 이것으로 성공했습니다.

#ifndef Token_h 
#define Token_h 

typedef struct Token { 
    int code; 
    char * string; 
    int string_length; 
} Token; 

#endif // Token_h 

main.c를

int main(int argc, char** argv) { 
    // Set up the scanner 
    yyscan_t scanner; 
    yylex_init(&scanner); 
    yyset_in(stdin, scanner); 

    // Set up the parser 
    void* parser = ParseAlloc(malloc); 

    // Do it! 
    Token t; 
    do { 
     t.code = yylex(scanner); 
     t.string = yyget_text(scanner); 
     t.string_length = yyget_leng(scanner); 
     Parse(parser, t.code, t); 
    } while (t.code > 0); 

    if (-1 == t.code) { 
     fprintf(stderr, "The scanner encountered an error.\n"); 
    } 

    // Cleanup the scanner and parser 
    yylex_destroy(scanner); 
    ParseFree(parser, free); 
    return 0; 
} 

language.y (발췌) token.h

class_interface ::= INTERFACE IDENTIFIER(A) class_inheritance END. 
{ 
    printf("defined class %.*s\n", A.string_length, A.string); 
} 

가 내의 printf 문을 참조하십시오? 내 토큰을 인쇄하려면 문자열과 길이를 사용하고 있습니다.

관련 문제