2013-06-09 1 views
0

flex 및 bison을 사용하여 간단한 스크립트 파일을 구문 분석하기 위해 스캐너 및 구문 분석기를 작성하려고합니다. 스크립트 파일의 첫 번째 행만 구문 분석 할 수 있습니다. 그런 다음 프로그램은 'yyerror : syntax error'오류로 종료됩니다. 내 프로그램이 스크립트의 다음 줄로 진행하도록하려면 어떻게해야합니까?Flex 및 Bison : 전체 스크립트 파일을 구문 분석 할 수 없습니다.

아래의 컴파일 옵션으로 Window7을 사용하고 있습니다.

편집 :

flex lex.l 
bison -d yacc.y 
g++ lex.yy.c yacc.tab.c -lfl -o scanner.exe 
여기

나는 .Y 파일 내 Script.txt를 파일을 .L 부착하고있다.

파일 : lex.l

%{ 
#include <iostream> 
#include <stdio.h> 
#include "yacc.tab.h" 
#define YY_DECL extern "C" int yylex() 

using namespace std; 
%} 

DOT    "." 
COLON   ":" 
SEMICOLON  ";" 
COMMA   "," 
ANGLE_LEFT  "<" 
ANGLE_RIGHT  ">" 
AT    "@" 
EQUAL   "=" 
SQUARE_OPEN  "[" 
SQUARE_CLOSE [^\\]"]" 
OPENBRACE  "\(" 
CLOSEBRACE  "\)" 
QUOTE   "\"" 
QUOTE_OPEN  "\"" 
QUOTE_CLOSE  [^\\]"\"" 
SPACE   " " 
TAB    "\t" 
CRLF   "\r\n" 
QUOTED_PAIR  "\\"[^\r\n] 
DIGIT   [0-9] 
ALPHA   [a-zA-Z] 
QTEXT   [0-9a-zA-Z!#$%&'()*+,\-.\/:;<=>[email protected]\[\]^_`{|}~] 
%% 

{SPACE}*{OPENBRACE}{SPACE}*  { return TOK_OPENBRACE; } 

{SPACE}*{CLOSEBRACE}{SPACE}* { return TOK_CLOSEBRACE; } 

{SPACE}*{SEMICOLON}{SPACE}*  { return TOK_SEMICOLON; } 

{SPACE}*{COMMA}{SPACE}*   { return TOK_COMMA; } 

{QUOTE_OPEN}({SPACE}*{QTEXT}*{QUOTED_PAIR}*)*{QUOTE_CLOSE} { 
           yylval.sval = &yytext[1]; 
           yylval.sval[strlen(yylval.sval) - 1] = '\0'; 
           return TOK_QUOTED_STRING; 
           } 

{DIGIT}+      { 
           yylval.lval = atoi(yytext); 
           return TOK_LONG; 
           } 

"true"|"false"     { 
           yylval.ival = ((0 == strcmp(yytext, "true")) ? 1 : 0); 
           return TOK_BOOL; 
           } 
^"function1"     { return TOK_FUNC1; } 
^"function2"     { return TOK_FUNC2; } 
^"function3"     { return TOK_FUNC3; } 

^{CRLF}       { return TOK_EMPTY_LINE; } 
{CRLF}       {} 
.        {}/* ignore unknown chars */ 

파일 : yacc.y

%{ 
#include <iostream> 
#include <stdio.h> 

using namespace std; 

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

int yyerror(const char *s); 
%} 

// Symbols. 
%union 
{ 
    char *sval; 
    long lval; 
    int  ival; 
}; 

%token TOK_FUNC1 
%token TOK_FUNC2 
%token TOK_FUNC3 

%token <sval> TOK_QUOTED_STRING 
%token <lval> TOK_LONG 
%token <ival> TOK_BOOL 

%token TOK_SEMICOLON 
%token TOK_OPENBRACE 
%token TOK_CLOSEBRACE 
%token TOK_COMMA 
%token TOK_EMPTY_LINE 

%start program 
%% 

program : func1 
     | func2 
     | func3 
     | empty_line 
     ; 

func1 : TOK_FUNC1 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
        { 
        cout << "function1:" << $3 << " " << $5 << " " << $7; 
        } 

func2 : TOK_FUNC2 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
        { 
         cout << "function2:" << $3 << " " << $5 << " " << $7; 
        } 

func3 : TOK_FUNC3 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
        { 
         cout << "function3:" << $3 << " " << $5 << " " << $7; 
        } 

empty_line : TOK_EMPTY_LINE 
        { 
        } 
%% 

int yyerror(const char *s) { 
    cout << "yyerror : " << s << endl; 
} 

int main(void) { 
    FILE * pt = fopen("script.txt", "r"); 
    yyin = pt; 
     yyparse();  
} 

파일 : Script.txt를

function1("scanner1", 1234, true); 
function2("scanner2", 4321, false); 
function3("scanner3", 0123, true); 

출력 :

function1:scanner1 1234 1 
yyerror : syntax error 

예상 출력 :

function1:scanner1 1234 1 
function2:scanner2 4321 0 
function3:scanner3

답변

0

문법의 시작 생산, program는 단 하나의 라인 (A FUNC1하는 FUNC2하는 func3, 또는 빈 줄을) 받아들입니다. 따라서 두 번째 줄을 허용하지 않습니다.

다른 많은 문제가 있습니다.

우선 flex는 표준 C I/O 라이브러리를 사용하여 ascii 모드에서 파일을 열어서 Windows에서도 CRLF로 \r을 볼 수있을 것이라고 믿지 않습니다.

두 번째로 yylval.sval = &yytext[1];yytext의 내용을 복사하지 않습니다. yytextflex에 속하므로 수정할 필요가 없습니다. 또한, 당신은 렉서가 값을 반환하자마자 flex가 그것을 수정할지도 모른다는 것을 알아야합니다. 따라서 strdup을 사용하여 사본을 만들어야하며 사본을 무료로 제공해야합니다.

+0

만 덕분에 (이 bison FAQ entry 참조). 나는 그것을 고쳤다. 당신이 말했듯이 '\ r \ n'은 '\ n'과 'yytext'로 대체되어야 'sval'에 덤프됩니다. – Sandy

0

다음은 수정 된 들소 파일 yacc.y 솔루션

%{ 
#include <iostream> 
#include <stdio.h> 

using namespace std; 

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

int yyerror(const char *s); 
%} 

// Symbols. 
%union 
{ 
    char *sval; 
    long lval; 
    int  ival; 
}; 

%token TOK_FUNC1 
%token TOK_FUNC2 
%token TOK_FUNC3 

%token <sval> TOK_QUOTED_STRING 
%token <lval> TOK_LONG 
%token <ival> TOK_BOOL 

%token TOK_SEMICOLON 
%token TOK_OPENBRACE 
%token TOK_CLOSEBRACE 
%token TOK_COMMA 
%token TOK_EMPTY_LINE 

%start program 
%% 

program : funcs 
     ; 

funcs : funcs func 
     | func 
     ; 

func : TOK_FUNC1 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
     { 
     cout << "function1:" << $3 << " " << $5 << " " << $7; 
     } 
     | TOK_FUNC2 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
     { 
      cout << "function2:" << $3 << " " << $5 << " " << $7; 
     } 
     | TOK_FUNC3 TOK_OPENBRACE TOK_QUOTED_STRING TOK_COMMA TOK_LONG TOK_COMMA TOK_BOOL TOK_CLOSEBRACE TOK_SEMICOLON 
     { 
      cout << "function3:" << $3 << " " << $5 << " " << $7; 
     } 
     | TOK_EMPTY_LINE 
     { 
     } 
%% 

int yyerror(const char *s) { 
    cout << "yyerror : " << s << endl; 
} 

int main(void) { 
    FILE * pt = fopen("script.txt", "r"); 
    yyin = pt; 
     yyparse();  
} 
관련 문제