2010-12-17 81 views
2

我使用flex和bison來實現解析器。我遇到的一個問題是,如何將單獨的flex文件的標記提供給解析器。當我試圖編譯我的parser.tab.c它抱怨"undefined reference to yylex"。 然後,我試圖在編譯時設置-d選項,並將頭文件包含到flex文件中。使用flex和Bison的解析器

我只是想知道使用flex和野牛的正確步驟(用相關的命令來編譯和運行)我正在使用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運行你的Flex文件之後,定義的函數。來自GCC的「未定義的yylex參考」告訴你,鏈接器找不到yylex的定義。你的問題是你正在試圖產生一個可執行的圖像沒有所有的作品。

例如,假設您有3個文件,main.c,flex.l,parser.y。你可以這樣做來編譯它們。

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選項告訴gcc編譯並生成一個目標文件(源代碼 - >編譯爲assembly-> assembly assembly)。它不會做任何連接。

現在進入如何使用make,你可以在谷歌上找到幾個優秀的教程。

0

如果你只包含2像flex.l和parser.y文件,並嘗試編譯手段,請這樣進行編譯

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

lfl是lexers的鏈接文件庫。如果缺少包含-lfl,則表示出現錯誤:未定義對yylex的引用。