2010-12-17 14 views
2

私は、パーサーを実装するためにflexとbisonを使用しています。私が遭遇した問題は、どのようにして別々のフレックスファイルのトークンをパーサーに与えることができるかということです。 parser.tab.cをコンパイルしようとすると約"undefined reference to yylex"という文句があります。 次に、コンパイル時に-dオプションを設定して、ヘッダーファイルを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と書くことができます。

出典:ドキュメント...

だから、あなたはそれがフレックス1を呼び出すようにyylex関数を記述する必要があります。

flexとbisonの両方が良い完全な例と完璧な文書を与える:

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 

これは実行可能ファイルを生成します。しかし、たくさんのファイルがたくさんあるとしたら、これはいつも非常に遅いでしょう。あなたは1つ1つずつコンパイルしたいでしょう。

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を伝えます。リンクはありません。

ここでは、makeの使い方について説明します。これは、Googleでいくつかの優れたチュートリアルを見つけることができます。

0

あなたはflex.lとparser.yのような唯一の2つのファイルが含まれていると手段をコンパイルしようとした場合、この

のgcc -o myexe parser.tab.c lex.yy.cを-lfl

のようにコンパイルしてください

lflはlexersのリンクファイルライブラリです。-lflを含めると、エラーが表示されます。yylexへの未定義の参照。

関連する問題