Парсер с использованием flex и Bison - PullRequest
2 голосов
/ 17 декабря 2010

Я использую flex и bison для реализации парсера. Проблема, с которой я столкнулся, заключается в том, как я могу передать токены отдельного гибкого файла парсеру. когда я пытаюсь скомпилировать parser.tab.c, он жалуется на "undefined reference to yylex". Затем я попытался установить параметр -d при компиляции и включить файл заголовка в файл flex.

Я просто хочу знать, как правильно использовать 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;
}

Ответы [ 3 ]

2 голосов
/ 17 декабря 2010

" yylex - это функция лексического анализатора, она распознает токены из входного потока и возвращает их анализатору. Bison не создает эту функцию автоматически, поэтому вы должны написать ее так, чтобы yyparse может вызвать его. "

Источник: документация ...

Так что вам нужно написать функцию yylex, чтобы она вызывала функцию flex.

И Flex, иБизоны дают хорошие полные примеры и отличную документацию:

0 голосов
/ 19 декабря 2013

Если у вас есть только 2 файла, таких как flex.l и parser.y, и вы пытаетесь скомпилировать средства, пожалуйста, скомпилируйте так:

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

lfl - это библиотека файлов ссылок для lexers.Если вы пропустили включение -lfl, это означает, что вы получили ошибку: неопределенная ссылка на yylex.

0 голосов
/ 17 декабря 2010

yylex - это функция, определенная после запуска файла flex через flex. «Неопределенная ссылка на yylex» от GCC говорит вам, что компоновщик не смог найти определение 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 компилировать и создавать объектный файл (исходный код-> скомпилирован в сборку-> сборка собрана). Это не делает никаких ссылок.

Теперь поговорим о том, как использовать make, в котором вы можете найти несколько отличных учебников в Google.

...