2016-09-23 5 views
1

문자열 상수를 처리하기 위해 플렉스 프로그램을 작성하고 있습니다.yymore()를 사용할 때 EOF에서 플렉스 오류 "end of buffer missed"가 발생했습니다.

문자열 내에서 입력 파일이 EOF를 만족하면 ERROR 토큰을 반환하고 싶습니다.

나는 파일이 인쇄 EOF와 "ERROR"을 충족 한 후 다음과 같은 오류 있어요 :

치명적인 플렉스 스캐너 내부 오류 - 버퍼의 끝이 여기에

을 놓친 내 코드입니다 : (나는 yymore() 함수 호출을 삭제하면이 오류를 재현 할 수있는 단순화 된 버전)

%option noyywrap 
    #define ERROR 300 
    #define STRING 301 
    char *text; 
%x str 

%% 

\"   {BEGIN(str); yymore();} 
<str>\"  {BEGIN(INITIAL); text=yytext; return STRING;} 
<str>.  {yymore();} 
<str><<EOF>> {BEGIN(INITIAL); return ERROR;} 

%% 

int main(){ 
    int token; 
    while((token=yylex())!=0){ 
     if(token==STRING) 
      printf("string:%s\n",text); 
     else if(token==ERROR) 
      printf("ERROR\n"); 
    } 
    return 0; 
} 

는 오류가 사라지고 프로그램이 종료 정상적으로 "ERROR"를 인쇄 한 후.

왜 이런 일이 발생하는지 궁금하며 yymore()을 제거하지 않고 해결하고 싶습니다.

답변

1

EOF 표시를받은 후 어휘 검사를 계속할 수 없으므로 <str><<EOF>> 규칙이 잘못되어 오류 메시지가 나타내는 내용입니다.

정의되지 않은 동작과 마찬가지로, 오류로 인해 작업이 잘못되었다고 생각하는 등의 임의의 동작이 발생할 수 있습니다. flex 버전에서는 예를 들어 yymore을 사용하지 않으면 이런 현상이 발생합니다.

EOF 수신 후 스캐너 루프가 다시 입력되지 않도록해야합니다. 예를 들어, 더 이상 토큰을 읽을 수 없다는 것을 나타내는 오류 코드를 반환 할 수 있습니다 (필요한 경우 다시 시작할 수있는 오류 표시와 반대). 또는 lexer에 플래그를 설정하여 복구 할 수없는 오류.

여기 (아무것도 다른 변화 때문에, 단지 규칙) 두 번째 전략의 예 :

%% 
       /* indented code before the first pattern is inserted 
       * at the beginning of yylex, allowing declaration of 
       * variables. The fatal_error flag is declared static, 
       * since this is not a reentrable lexer. If it were 
       * reentrable, we'd put the flag in the lexer context 
       * (as part of the "extra data"), which would be a lot cleaner. 
       */ 
       static int fatal_error = 0; 
       /* If the error we last returned was fatal, we do 
       * not re-enter the scanner loop; we just return EOF 
       */ 
       if (fatal_error) { 
        fatal_error = 0; /* reset the flag for reuse */ 
        return 0; 
       } 

\"   {BEGIN(str); yymore();} 
<str>\"  {BEGIN(INITIAL); text=yytext; return STRING;} 
<str>.  {yymore();} 
<str><<EOF>> {BEGIN(INITIAL); 
       fatal_error = 1; /* Set the fatal error flag */ 
       return ERROR;} 

%% 

또 다른 가능한 해결책은 yylex 각 토큰으로 파서를 호출하는 "푸시 파서"를 사용하는 것입니다, 다른 방법으로 라운드 대신. bison은이 스타일을 지원하며 훨씬 더 편리합니다. 특히, 하나의 액션이 하나 이상의 토큰을 파서로 보내도록 허용한다.이 경우에 정적 로컬 플래그에 대한 필요성이 제거된다.