2013-09-29 3 views
0

최근에 GNU BisonFlex을 사용하여 인터프리터를 작성하려고했습니다. 내가 인터프리터가 인식 할 텍스트는 print "Hello"이고, 나는 다음과 같은 시도 :Bison/Flex 구문 분석 파일

flex file:

%{ 
#include <iostream> 
using namespace std; 
#define YY_DECL extern "C" int yylex() 
#include "gbison.tab.h" 
%} 
%% 
[ \t\n]   ; 
'\"'    return QUOTE; 
[a-zA-Z0-9]+  { yylval.sval = strdup(yytext); return STRING; } 
%% 

bison file:

%{ 
#include <cstdio> 
#include <cstring> 
#include <iostream> 
using namespace std; 

extern "C" int yylex(); 
extern "C" int yyparse(); 
extern "C" FILE* yyin; 

void yyerror (const char* s); 
%} 

%union { 
    char* sval; 
} 

%token <sval> STRING 
%token QUOTE 
%% 

str: 
    STRING QUOTE STRING QUOTE 
    { 
     if (strcmp($1, "print") == 0) 
     { 
      cout << $3 << flush; 
     } 
     if (strcmp($1, "println") == 0) 
     { 
      cout << $3 << endl; 
     } 
    } 
    ; 
%% 

main(int argc, char* argv[]) 
{ 
    FILE* input = fopen(argv[1], "r"); 
    if (!input) 
    { 
     cout << "Bad input. Nonexistant file" << endl; 
     return -1; 
    } 

    yyin = input; 

    do 
    { 
     yyparse(); 
    } while (!feof(yyin)); 

} 
void yyerror(const char* s) 
{ 
    cout << "Error. " << s << endl; 
    exit(-1); 
} 

을하지만 컴파일 된 프로그램에 print "hello"을 통과 할 때 내가 얻을 : 를 "Error. syntax error

나는 그쪽으로 생각한다. 문제는 STRING QUOTE STRING QUOTE이지만 확실하지 않습니다. 정확하게 무엇이 잘못 될까요? 통역사에게 hello을 인쇄하게하려면 어떻게해야합니까?

답변

1

답변은 아래에 나와 있습니다. 그러나 다음 내용이 낚시 지침으로 더 일반적으로 유용하기를 바랍니다.

다양한 디버깅 도구가 도움이됩니다.

-d, --debug

는 "디버그"모드에서 생성 된 스캐너를 실행한다 : 특히, 플렉스는 -d 플래그를 제공합니다. 패턴이 인식되고 전역 변수 yy_flex_debug이 기본값이 아닌 0이 아닌 경우 스캐너는 stderr 행에 & hellip; (flex manual)

bison도 디버그 기능을 제공합니다. (bison manual)

는 추적 기능의 편집 가능하게하는 몇 가지 방법이 있습니다
  • 매크로 YYDEBUG 중 & hellip을;
  • 옵션 -t (POSIX Yacc 호환) & hellip;
  • 옵션 --debug (들소 확장 기능) & hellip;
  • 지침 %debug & hellip;
언제든지 디버그 옵션 이 항상 가능하도록 설정하는 것이 좋습니다.
& hellip;
추적 기능을 사용하여 프로그램을 컴파일하고 나면 추적을 요청하는 방법은 변수 yydebug에 0이 아닌 값을 저장하는 것입니다. C 코드가 수행하도록 ( main, 아마도) 또는 이 C 디버거로 값을 변경할 수 있습니다.

또한 flex는 인식 할 수없는 문자가 출력에 에코되게하는 자동 규칙을 삽입합니다. ("기본적으로 플렉스 스캐너가 일치하지 않는 텍스트 출력에 복사됩니다"- Some simple examples) 오류 메시지에 추가 "이 프로그램에서 인쇄되는 이유 그건 :

"Error. syntax error 
^ 

는 약간의 그 미묘한.추적 flex은 당신을 더 직접적으로 보였을 것입니다.

그래서, 결국, 문제 (들) :

  1. 플렉스 패턴 '\"'일치하지 않습니다 "을 그것과 일치 '."', 작은 따옴표가되지 않기 때문에 플렉스 특수. 그게 당신의 구문 분석이 실패하는 이유입니다.

  2. 프로그램을 수정하면 단일 명령을 구문 분석 할 수 있지만 동일한 입력으로 두 개의 명령을 보내려고하면 구문 오류가 발생합니다. bison은 렉서에서 END 토큰을받을 때까지 파싱을 수행하고 렉서 (기본값)는 입력이 끝나면 END 토큰 만 제공하기 때문입니다. 당신은, 수 ((ACCEPT를 사용하여) (권장하지 않음)

  3. 파서 동작 (예를 들어, 다른 상황에서 새로운 라인을 END을 보내)

    • 렉서의 동작을 변경할 수 있습니다 하지만 거의 필요하지 않음)

    • 문법을 사용하면 원하는 수의 문을 인식 할 수 있습니다. (를 권장)