2010-12-17 4 views
2

저는 flex와 bison을 사용하여 파서를 구현하고 있습니다. 문제는 필자가 별도로 구한 플렉스 파일의 토큰을 파서에 어떻게 제공 할 수 있는가하는 점이다. 내 컴파일하려고 할 때 parser.tab.c"undefined reference to yylex" 불평. 그런 다음 컴파일 할 때 -d 옵션을 설정하고 헤더 파일을 flex 파일에 포함하려고했습니다.flex와 Bison을 사용하는 파서

나는 단지 flex와 bison (관련 명령을 컴파일하고 실행하는 데 사용)의 올바른 단계를 알고 싶습니다. gcc 컴파일러를 사용하고 있습니다. 많은 고맙습니다

/* Token Scanner for C- language */ 

%{ 

#include <stdio.h> 
#include <stdlib.h> 
#include "parser.tab.h" 
extern YYSTYPE yylval; 



%} 



digit    [0-9] 
letter    [a-zA-Z] 
NUM    {digit}+ 
ID    {letter}+ 
KEY_WORD    else|if|int|return|void|while 
PLUS_OPERATOR   "+" 
MINUS_OPERATOR    "-" 
MUL_OPERATOR     "*" 
DIV_OPERATOR     "/" 
LESS_THAN_OPERATOR   "<" 
LESS_THAN_OR_EQUAL_OPER  "<=" 
GREATER_THAN_OPERATOR   ">" 
GREATER_THAN_OR_EQUAL_OPERATOR ">=" 
EQUAL_OPERATOR   "=" 
OBJ_EQUAL_OPERATOR   "==" 
NOT_EQUAL_OPERATOR   "!=" 
COMMA_SYMBOL    "," 
SEMI_COLON_SYMBOL  ";" 
LEFT_BRAC_SYMBOL   "(" 
RIGHT_BRAC-SYMBOL  ")" 
LEFT_SQUARE_BRAC_SYMBOL   "[" 
RIGHT_SQUARE_BRAC_SYMBOL  "]" 
LEFT_CURLY_BRAC_SYMBOL  "{" 
RIGHT_CURLY_BRAC_SYMBOL  "}" 
LEFT_COMMENT    "/*" 
RIGHT_COMMENT   "*/" 
ELSE    "else" 
IF    "if" 
INT    "int" 
RETURN    "return" 
VOID    "void" 
WHILE    "while" 

SYMBOL    "+"|"-"|"*"|"/"|"<"|"<="|">"|">="|"=="|"!="|"="|";"|","|"("|")"|"{"|"}"|"["|"]"|"/*"|"*/"  

WHITESPACE    [ \t\n]+ 
COMMENT    "/*"(.)*({WHITESPACE})*(.)*"*/" 

ERROR1    {NUM}(({ID}|{KEY_WORD})|{NUM})+ 
ERROR2    {ID}(({NUM}|{KEY_WORD})|{ID})+ 
ERROR3    {KEY_WORD}(({ID}|{NUM})|{KEY_WORD})+ 

ERROR     ERROR1|ERROR2|ERROR3 


%% 


{NUM}   { 
       return NUM; 
       } 

{ELSE}    { 
       return ELSE; 
         } 

{IF}    { 
       return IF; 
         } 

{INT}   { 
       return INT; 
         } 

{RETURN}    { 
       return RETURN; 
         } 

{VOID}    { 
       return VOID; 
         } 

{WHILE}    { 
       return WHILE; 
         } 


{ID}    { 
       return ID; 
       } 

{PLUS_OPERATOR}  { 
       return PLUS_OPERATOR; 
        } 

{MINUS_OPERATOR} { 
       return MINUS_OPERATOR; 
        } 

{MUL_OPERATOR}   { 
       return MUL_OPERATOR; 
         } 
{DIV_OPERATOR}   { 
       return DIV_OPERATOR; 
         } 
{LESS_THAN_OPERATOR} { 
       return LESS_THAN_OPERATOR; 
         } 
{LESS_THAN_OR_EQUAL_OPER} { 
       return LESS_THAN_OR_EQUAL_OPER; 
         } 

{GREATER_THAN_OPERATOR} { 
       return GREATER_THAN_OPERATOR; 
         } 

{GREATER_THAN_OR_EQUAL_OPERATOR} { 
       return GREATER_THAN_OR_EQUAL_OPERATOR; 
         } 
{EQUAL_OPERATOR}  { 
       return EQUAL_OPERATOR; 
         } 
{OBJ_EQUAL_OPERATOR} { 
       return NOT_EQUAL_OPERATOR; 
         } 
{NOT_EQUAL_OPERATOR} { 
       return NOT_EQUAL_OPERATOR; 
         } 
{COMMA_SYMBOL} { 
       return COMMA_SYMBOL; 
         } 
{SEMI_COLON_SYMBOL} { 
       return SEMI_COLON_SYMBOL; 
         } 

{LEFT_BRAC_SYMBOL} { 
       return LEFT_BRAC_SYMBOL; 
         } 
{RIGHT_BRAC-SYMBOL} { 
       return RIGHT_BRAC_SYMBOL; 
         } 

{LEFT_SQUARE_BRAC_SYMBOL} { 
       return LEFT_SQUARE_BRAC_SYMBOL; 
         } 
{RIGHT_SQUARE_BRAC_SYMBOL} { 
       return RIGHT_SQUARE_BRAC_SYMBOL; 
         } 
{LEFT_CURLY_BRAC_SYMBOL} { 
       return LEFT_CURLY_BRAC_SYMBOL; 
           } 
{RIGHT_CURLY_BRAC_SYMBOL} { 
       return RIGHT_CURLY_BRAC_SYMBOL; 
           } 

{LEFT_COMMENT} { 
       return LEFT_COMMENT; 
           } 

{RIGHT_COMMENT} { 
       return RIGHT_COMMENT; 
           } 
{WHITESPACE} { 

           } 

{ERROR}   { 

           }    
%% 

main(argc, argv) 
int argc; 
char **argv; 
    { 
    ++argv, --argc; /* skip over program name */ 
    if (argc > 0) 
      yyin = fopen(argv[0], "r"); 
    else 
      yyin = stdin; 

    yylex(); 
    } 


int yywrap(void){return 1;} 

파서 :.

%{ 
#include <stdio.h> 
#include <ctype.h> 
#define YYDEBUG 1 

%} 

%token ID NUM PLUS_OPERATOR MINUS_OPERATOR MUL_OPERATOR DIV_OPERATOR LESS_THAN_OPERATOR LESS_THAN_OR_EQUAL_OPER GREATER_THAN_OPERATOR GREATER_THAN_OR_EQUAL_OPERATOR EQUAL_OPERATOR OBJ_EQUAL_OPERATOR   NOT_EQUAL_OPERATOR COMMA_SYMBOL SEMI_COLON_SYMBOL LEFT_BRAC_SYMBOL RIGHT_BRAC_SYMBOL LEFT_SQUARE_BRAC_SYMBOL RIGHT_SQUARE_BRAC_SYMBOL LEFT_CURLY_BRAC_SYMBOL RIGHT_CURLY_BRAC_SYMBOL   LEFT_COMMENT RIGHT_COMMENT ELSE IF INT RETURN VOID WHILE 

%expect 1 


%% 


program: declaration_list 
; 

declaration_list: declaration_list declaration 
    | declaration     { printf("njuwandusanduansduasdsdsdsa"); } 
; 

declaration : var_declaration 
    | fun_declaration    { printf("njuwandusanduansduasdsdsdsa");} 
; 

var_declaration : type_specifier ID SEMI_COLON_SYMBOL 
    | type_specifier ID LEFT_SQUARE_BRAC_SYMBOL NUM RIGHT_SQUARE_BRAC_SYMBOL COMMA_SYMBOL  { printf("njuwandusanduansduasdsdsdsa"); } 
; 

type_specifier : INT 
    | VOID     { printf("njuwandusanduansduasdsdsdsa");} 
; 

fun_declaration : type_specifier ID LEFT_BRAC_SYMBOL params RIGHT_BRAC_SYMBOL compound_stmt 
; 

params : param_list 
    | VOID 
; 

param_list : param_list COMMA_SYMBOL param 
    | param 
; 

param : type_specifier ID 
    | type_specifier ID LEFT_SQUARE_BRAC_SYMBOL RIGHT_SQUARE_BRAC_SYMBOL 
; 
compound_stmt : LEFT_CURLY_BRAC_SYMBOL local_declarations statement_list RIGHT_CURLY_BRAC_SYMBOL 
; 

local_declarations : local_declarations var_declaration 
    | /* empty */ 
; 

statement_list : statement_list statement 
    |/* empty */ 
; 

statement : expression_stmt 
    | compound_stmt 
    | selection_stmt 
    | iteration_stmt 
    | return_stmt 
; 

expression_stmt : expression SEMI_COLON_SYMBOL 
    | SEMI_COLON_SYMBOL 
; 

selection_stmt : IF LEFT_BRAC_SYMBOL expression RIGHT_BRAC_SYMBOL statement 
    | IF LEFT_BRAC_SYMBOL expression RIGHT_BRAC_SYMBOL statement ELSE statement 
; 

iteration_stmt : WHILE LEFT_BRAC_SYMBOL expression RIGHT_BRAC_SYMBOL statement 
; 

return_stmt : RETURN SEMI_COLON_SYMBOL 
    | RETURN expression SEMI_COLON_SYMBOL 
; 

expression: var EQUAL_OPERATOR expression 
    | simple_expression 
; 

var : ID 
    | ID LEFT_SQUARE_BRAC_SYMBOL expression RIGHT_SQUARE_BRAC_SYMBOL 
; 

simple_expression : additive_expression relop additive_expression 
    | additive_expression 
; 

relop : LESS_THAN_OR_EQUAL_OPER 
    | LESS_THAN_OPERATOR 
    | GREATER_THAN_OPERATOR 
    | GREATER_THAN_OR_EQUAL_OPERATOR 
    | OBJ_EQUAL_OPERATOR 
    | NOT_EQUAL_OPERATOR 
; 

additive_expression : additive_expression addop term 
     | term   
; 

addop : PLUS_OPERATOR 
    | MINUS_OPERATOR { printf("njuwandusanduansduasdsdsdsa"); } 
; 

term : term mulop factor  { $$ = $1 + $3; } 
    | factor 
; 

mulop : MUL_OPERATOR 
    | DIV_OPERATOR 
; 

factor : LEFT_BRAC_SYMBOL expression RIGHT_BRAC_SYMBOL 
    | var 
    | call 
    | NUM 
; 

call : ID LEFT_BRAC_SYMBOL args RIGHT_BRAC_SYMBOL 
; 

args : arg_list 
    |/* empty */ 
; 

arg_list : arg_list COMMA_SYMBOL expression 
    | expression 

; 



%% 

main() 
{ 

extern int yydebug; 
yydebug=1; 
return yyparse(); 
} 


int yyerror(char * s) 
{ 
fprintf(stderr, "%s\n",s); 
return 0; 
} 

답변

2

"는 yylex, 그것은 어휘 분석기 기능 입력 스트림에서 토큰을 인식하고 파서에게 반환 들소하지 않습니다 이 함수를 자동으로 작성하여 yyparse이 호출 할 수 있도록 작성해야합니다. "

출처 : 문서 ...

그래서 당신은 플렉스를 호출 할 수 있도록는 yylex 함수를 작성해야합니다.

Flex와 들소 모두 좋은 전체 예제와 완벽한 문서를 제공합니다 :

0

는 yylex는 flex를 통해 플렉스 파일을 실행 한 후 정의 된 함수입니다. GCC에서 "정의되지 않은 yylex 참조"는 링커가 yylex의 정의를 찾을 수 없다는 것을 알려줍니다. 문제는 모든 부분이없는 실행 가능 이미지를 생성하려고한다는 것입니다.

예를 들어, main.c, flex.l, parser.y 파일이 3 개 있다고 가정합니다. 당신이 그들을 컴파일 할 수 있습니다.

flex flex.l 
bison -d parser.y 
gcc main.c parser.tab.c lex.yy.c -o myEXE 

이렇게하면 실행 파일이 생성됩니다. 그러나 많은 파일이 있고 이것을 항상 매우 천천히한다고 가정 해보십시오. 한 조각 씩 컴파일하고 싶을 것입니다.

flex flex.l 
gcc -c lex.yy.c -o lex.o 
bison -d parser.y 
gcc -c parser.tab.c -o parser.o 
gcc -c main.c -o main.o 
gcc main.o parser.o lex.o 

-c 옵션 (소스 코드 -> assembly- 컴파일> 어셈블리가 조립) 컴파일하고 오브젝트 파일을 생성하는 GCC를 알려줍니다. 어떤 연결도하지 않습니다.

이제는 Google에서 여러 가지 유용한 자습서를 찾을 수있는 make을 사용하는 방법에 대해 알아 보았습니다.

0

당신이 flex.l 및 parser.y 같은 단지 2 파일이 포함이

의 gcc -o myexe parser.tab.c의 lex.yy.c의 -lfl

처럼 컴파일하십시오 수단을 컴파일하려고하면

lfl은 lexers 용 링크 파일 라이브러리입니다. -lfl을 포함하지 않으면 오류가 발생했음을 의미합니다. yylex에 대한 정의되지 않은 참조.