2017-04-13 4 views
1

J'essaye de construire un analyseur lexical avec FLEX sur Windows. Je reçois toujours une erreur:Comment utiliser yylval dans flex

"undefined reference to `yylval'"

Je déclare yylval comme jusqu'à type extern où toutes les définitions sont faits comme suit:

%option noyywrap 
    %{ 
     #include<stdio.h> 
     #include<stdlib.h> 
     #include "tokens.h" 
     int nline = 1; 
     int size_token_array = 100; 
     int number_of_tokens_in_array = 0; 
     int inc_token_array = 50; 
     token *token_store ; 
     extern yylval; 

    %} 
    delim [ \t] 
    delim_nl [\n] 
    ws {delim}+ 
    nl {delim_nl}+ 
    letter [a-z] 
    digit [0-9] 
    id {letter}(letter.digit)* 
    int_num (0|([+-]?([1-9]{digit}*))) 
    real_num [+-]?{digit}+(\.{digit}+) 
    rel_op ">"|"<"|"<="|">="|"=="|"!=" 
    binary_ar_op "+"|"-"|"*"|"/"|"=" 
    task_id {letter}(letter+digit)* 
    signal_id {letter}(letter+digit)* 

    %% 
    "parbegin" {create_and_store_token(TOKEN_PARBEGIN,yytext,nline); return 1;} 
    "parend" {create_and_store_token(TOKEN_PAREND,yytext,nline); return 1;} 
    "task" {create_and_store_token(TOKEN_TASK,yytext,nline); return 1;} 
    "{" {create_and_store_token('{',yytext,nline); return 1;} 
    "}" {create_and_store_token('}',yytext,nline); return 1;} 
    "begin" {create_and_store_token(TOKEN_BEGIN,yytext,nline); return 1;} 
    "end" {create_and_store_token(TOKEN_END,yytext,nline); return 1;} 
    "integer" {create_and_store_token(TOKEN_INTEGER,yytext,nline); return 1;} 
    "real" {create_and_store_token(TOKEN_REAL,yytext,nline); return 1;} 
    "||" {create_and_store_token(TOKEN_PARALLEL,yytext,nline); return 1;} 
    ";" {create_and_store_token(';',yytext,nline); return 1;} 
    "," {create_and_store_token(',',yytext,nline); return 1;} 
    "do" {create_and_store_token(TOKEN_DO,yytext,nline); return 1;} 
    "until" {create_and_store_token(TOKEN_UNTIL,yytext,nline); return 1;} 
    "od" {create_and_store_token(TOKEN_OD,yytext,nline); return 1;} 
    "send" {create_and_store_token(TOKEN_SEND,yytext,nline); return 1;} 
    "accept" {create_and_store_token(TOKEN_ACCEPT,yytext,nline); return 1;} 
    "(" {create_and_store_token('(',yytext,nline); return 1;} 
    ")" {create_and_store_token(')',yytext,nline); return 1;} 
    "<" {create_and_store_token(LT,yytext,nline); yylval=rel_op; return 1;} 
    ">" {create_and_store_token(GT,yytext,nline); yylval=rel_op; return 1;} 
    "<=" {create_and_store_token(LE,yytext,nline); yylval=rel_op; return 1;} 
    ">=" {create_and_store_token(GE,yytext,nline); yylval=rel_op; return 1;} 
    "==" {create_and_store_token(EQ,yytext,nline); yylval=rel_op; return 1;} 
    "!=" {create_and_store_token(NE,yytext,nline); yylval=rel_op; return 1;} 
    "*" {create_and_store_token('*',yytext,nline); yylval=binary_ar_op; return 1;} 
    "/" {create_and_store_token('/',yytext,nline); yylval=binary_ar_op; return 1;} 
    "+" {create_and_store_token('+',yytext,nline); yylval=binary_ar_op; return 1;} 
    "-" {create_and_store_token('-',yytext,nline); yylval=binary_ar_op; return 1;} 
    "=" {create_and_store_token('=',yytext,nline); yylval=binary_ar_op; return 1;} 
    {ws} ; 
    {nl} nline++; 
    id {create_and_store_token(TOKEN_ID,yytext,nline); return 1;} 
    int_num {create_and_store_token(TOKEN_INT_NUM,yytext,nline); return 1;} 
    real_num {create_and_store_token(TOKEN_REAL_NUM,yytext,nline); return 1;} 
    binary_ar_op {create_and_store_token(TOKEN_AR_OP,yytext,nline); return 1;} 
    "task_id" {create_and_store_token(TOKEN_TASK_ID,yytext,nline); return 1;} 
    "signal_id" {create_and_store_token(TOKEN_SIGNAL_ID,yytext,nline); return 1;} 

    %% 
    int main() 
    { 
     token_store = (token*)calloc(size_token_array,sizeof(token)); 
     free(token_store); 
     return 0; 

    } 

    void create_and_store_token(int token_type,char* token_lexeme,int line_number){ 

     token new_token; 
     new_token.ivalue = token_type; 
     new_token.lexema = token_lexeme; 
     new_token.line_number = line_number; 

     if(size_token_array == (number_of_tokens_in_array-10)){ 

      token_store = (token*)realloc(token_store,inc_token_array*sizeof(token)); 
      size_token_array+=inc_token_array; 
      number_of_tokens_in_array++; 
      token_store[number_of_tokens_in_array]= new_token; 

     } 
     else{ 
      token_store[number_of_tokens_in_array]= new_token; 
      number_of_tokens_in_array++; 

     } 
    } 

    int nextToken(){ 
     return yylex(); 
    } 

    void backToken(){ 
     token_store[number_of_tokens_in_array].ivalue = 0; 
     token_store[number_of_tokens_in_array].lexema = ""; 
     token_store[number_of_tokens_in_array].line_number = 0; 
     number_of_tokens_in_array--; 
    } 

Quelqu'un a une idée comment dois-je résoudre ce problème?

Répondre

1

extern yylval; signifie que yylval est défini ailleurs. Donc vous devez le faire.

Habituellement, il est défini dans l'analyseur généré par yacc/bison, de sorte que le nom peut être résolu lorsque vous liez le scanner et l'analyseur. Si vous n'utilisez pas bison/yacc, vous devrez définir vous-même yylval. (Si vous en avez réellement besoin, votre code ne donne pas grand-chose de ce dont vous avez besoin.)

Par ailleurs, votre code a beaucoup d'autres problèmes. Un exemple particulièrement flagrant est que vous ne pouvez pas utiliser la valeur du pointeur yytext après le passage du scanner au jeton suivant. Si vous avez besoin d'une copie persistante de la chaîne pointée par yytext, vous devez faire votre propre copie (et libérer la mémoire allouée pour la copie quand elle n'est plus nécessaire.)

Aussi beaucoup de vos expressions régulières sont incorrectes . Macro (utilisations « définitions ») doivent être entourés d'accolades, de sorte

id {create_and_store_token(TOKEN_ID,yytext,nline); return 1;} 

ne correspond pas à ce que vous attendez; il ne correspondra qu'aux deux caractères de la séquence id. Changer cela à {id} est un début, mais la définition de id est également incorrecte. Personnellement, j'évite les macros car elles n'ajoutent aucune valeur au code, IMO; ils créent souvent de la confusion. Par exemple, votre définition de letter inclut uniquement des lettres minuscules, ce qui ne serait pas du tout évident pour quelqu'un qui lit votre code. Il est préférable d'utiliser des classes de caractères Posix, qui ne nécessitent pas de définitions et dont les significations ne sont pas ambiguës: [[: alpha:]] pour les lettres, [[:lower:]] pour les lettres minuscules, [[:alnum:]] pour les lettres ou les chiffres, etc.