0
votes

Im building my files with yacc -d calclang.y

%{ 
#include <stdlib.h>
#include <stdio.h>
void yyerror(const char *str);


%}

%union 
{
    int ival; 
    float fval;
    char* word;
}
%start line
%type <word> wexp
%type <ival> iexp
%type <fval> fexp

%left PLUS MINUS
%left STAR DIV MOD
%left POW
%token GT
%token LT
%token ASGN
%token LP
%token RP
%token LB
%token RB
%token NOT
%token GTEQ
%token LTEQ
%token EQTO
%token NOTEQ
%token HORN
%token QMARK
%token <word> WORD
%token <fval> FLOAT
%token <ival> INTEGER


%%

line    : HORN wexp QMARK   {   printf("=\t%s", $2);    }
        | HORN iexp QMARK   {   printf("=\t%d", $2);    }
        | HORN fexp QMARK   {   printf("=\t%f", $2);    }
        ;

iexp    : iexp MINUS iexp   { $$ = $1 - $3;             }
        | iexp PLUS iexp    { $$ = $1 + $3;             }
        | INTEGER           { $$ = $1;                  }
        ;

fexp    : FLOAT             { $$ = $1;                  }
        ;

wexp    : WORD              { $$ = $1;                  }
        ;
%%


int main(){
    return yyparse();
}

void yyerror(const char *str)
{
        printf("error: %s\n",str);
}

and

flex calclang.l

%option noyywrap

%{
#include "y.tab.h"
%}

%%
"horn" | "HORN" {   return HORN;                                }
[1-9][0-9]*     {   return INTEGER; yylval.ival = atoi(yytext); }
[0-9]+"."[0-9]+ {   return FLOAT;   yylval.fval = atof(yytext); }
">="            {   return GTEQ;                                }
"<="            {   return LTEQ;                                }
"=="            {   return EQTO;                                }
"!="            {   return NOTEQ;                               }
"+"             {   return PLUS;                                }
"-"             {   return MINUS;                               }
"*"             {   return STAR;                                }
"/"             {   return DIV;                                 }
"^"             {   return POW;                                 }
"%"             {   return MOD;                                 }
">"             {   return GT;                                  }
"<"             {   return LT;                                  }
"("             {   return LP;                                  }
")"             {   return RP;                                  }
"="             {   return ASGN;                                }
"{"             {   return LB;                                  }
"}"             {   return RB;                                  }
"!"             {   return NOT;                                 }
"?"             {   return QMARK;                               }
[a-zA-Z]*       {   return WORD;    yylval.word = yytext;       }
[ \t\n\r]       {;                                              }
.               {;                                              }
%%

Then I'm using gcc y.tab.c lex.yy.c -o test

but I receive the following error message:

calclang.l:9:10: error: ‘INTEGER’ undeclared (first use in this function)
calclang.l:9:10: note: each undeclared identifier is reported only once for each function it appears in
calclang.l:9:19: error: ‘yylval’ undeclared (first use in this function)
calclang.l:10:10: error: ‘FLOAT’ undeclared (first use in this function)
calclang.l:11:10: error: ‘GTEQ’ undeclared (first use in this function)
calclang.l:12:10: error: ‘LTEQ’ undeclared (first use in this function)
calclang.l:13:10: error: ‘EQTO’ undeclared (first use in this function)
calclang.l:14:10: error: ‘NOTEQ’ undeclared (first use in this function)
calclang.l:15:10: error: ‘PLUS’ undeclared (first use in this function)
calclang.l:16:10: error: ‘MINUS’ undeclared (first use in this function)
calclang.l:17:10: error: ‘STAR’ undeclared (first use in this function)
calclang.l:18:10: error: ‘DIV’ undeclared (first use in this function)
calclang.l:19:10: error: ‘POW’ undeclared (first use in this function)
calclang.l:20:10: error: ‘MOD’ undeclared (first use in this function)
calclang.l:21:10: error: ‘GT’ undeclared (first use in this function)
calclang.l:22:10: error: ‘LT’ undeclared (first use in this function)
calclang.l:23:10: error: ‘LP’ undeclared (first use in this function)
calclang.l:24:10: error: ‘RP’ undeclared (first use in this function)
calclang.l:25:10: error: ‘ASGN’ undeclared (first use in this function)
calclang.l:26:10: error: ‘LB’ undeclared (first use in this function)
calclang.l:27:10: error: ‘RB’ undeclared (first use in this function)
calclang.l:28:10: error: ‘NOT’ undeclared (first use in this function)
calclang.l:29:10: error: ‘QMARK’ undeclared (first use in this function)
calclang.l:30:10: error: ‘WORD’ undeclared (first use in this function)

I've looked at other posts, and they said to have the #include y.tab.h but I already have that. So I've hit a roadblock. Why are all of my tokens undeclared? Thank you!

2
How about checking the generated y.tab.h file to verify that it defines all the expected symbols, and checking the generated lex.yy.c to verify that it in fact #includes y.tab.h? Also, does the compiler emit any other warning or error messages before the ones you present?John Bollinger
the y.tab.h has all the defines, but lex.yy.c doesnt have the #include for y.tab.h. Any theories as to why would this happen?Chris Phillips
@ChrisPhillips: The include is not at the beginning of lex.yy.c. Are you sure it is not present? It might be several hundred lines into the file; you'll need to search with a text editor or grep. It all works ok on my system; what version of flex and bison are you using?rici
flex 2.5.35 bison 2.5 -edit: i just ran a search, and the include isnt in lex.yy.cChris Phillips
Your code works for me (in the sense that a program can successfully be built from the generated files). If it's not working for you then perhaps your intermediate files are stale -- try running flex again, and make sure that lex.yy.c is in fact regenerated. Also, make sure that there's no possibility of confusion between different source or intermediate files of the same name in different directories.John Bollinger

2 Answers

2
votes

Use the -d option when you compile the yacc file. the -d option will write the y.tab.h header file. it is because of that lex is not identifying any of the tokens

    $lex filename.l
    $yacc -d filename.y
    $cc lex.yy.c y.tab.c -ll -ly

hope this helps :)

1
votes

This is not directly related to your question (as far as I know) but it definitely needs to be fixed:

"horn" | "HORN" {   return HORN;                                }

Flex regular expressions cannot have spaces. This is being parsed by flex as a | action, not as a regex operator, although it's not a valid | action either because that should be the last token on the line. I think that most versions of flex will just ignore the rest of the line, but I'm by no means sure. You should remove the spaces:

"horn"|"HORN"   {   return HORN;                                }

Also, the action here (and in some other lines):

[1-9][0-9]*     {   return INTEGER; yylval.ival = atoi(yytext); }

should generate a warning when compiled, because the statement following a return statement is never executed. (You should use -Wall in your gcc command to see the warnings.) In other words, the action in normal C code, so the assignment to yylval.ival cannot be executed.