Bison infix calculator always evaluates as 0 - c

I'm reading a book I found on the Internet about GNU Flex/Bison. And it's pretty cool. One of the examples involves writing an infix calculator. And that goes fine.
The problem is, the book uses int as YYSTYPE, which creates obvious issues when, say, dividing 1 by 2. So I decided I'd modify the program to use float instead. So far, so good. The program (source is given below) compiles fine, but always gives an answer of 0, no matter what the calculation is. I've no idea how to debug it either, as it's obviously generated code.
calc.l
%{
#include "parser.h"
%}
%%
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
[0-9]+ {
yylval = atof(yytext);
return NUMBER;
}
\n { return EOL; }
[ \t] { ; }
. { yyerror("Unknown symbol"); }
%%
calc.y
%{
#include <stdio.h>
#define YYSTYPE float
%}
%token NUMBER
%token ADD SUB MUL DIV
%token EOL
%%
/* List of expressions */
calclist:
| calclist AS_result EOL { printf("%f\n-> ", $2); }
;
/* Add/subtract result. Evaluated after multiply/divide result */
AS_result: MD_result
| AS_result ADD MD_result { $$ = $1 + $3; }
| AS_result SUB MD_result { $$ = $1 - $3; }
;
/* Multiply/divide result. Evaluated first. */
MD_result: NUMBER
| MD_result MUL NUMBER { $$ = $1 * $3; }
| MD_result DIV NUMBER { $$ = $1 / $3; }
;
%%
int yyerror(char *msg)
{
printf("Error: '%s'\n", msg);
return 0;
}
int main(int argc, char **argv)
{
printf("-> ");
yyparse();
return 0;
}
Makefile
make: calc.l calc.y
bison -Wall -o parser.c --defines=parser.h calc.y
flex -o scanner.c calc.l
cc -ggdb -o calc scanner.c parser.c -lfl
clean:
rm -f parser.c parser.h scanner.c calc.c calc
Example run
michael#michael-desktop:~/code/calculator$ ./calc
-> 1 + 2
0.000000
-> ^C
michael#michael-desktop:~/code/calculator$
Feedback on any part of the code is appreciated as well as the actual problem. Cheers!

You're right, it works only for division -- strange.. I haven't noticed, shame on me.
Here is another thing to try:
calc.y:
%{
#include <stdio.h>
%}
%union { double d; }
%token <d> NUMBER
%token ADD SUB MUL DIV
%token EOL
%type <d> MD_result AS_result
%%
calc.l: change the line "yylval = atof(yytext);" with:
yylval.d = atof(yytext);
Now it says:
-> 1+2
3.000000
-> 2*3
6.000000
-> 4-5
-1.000000
-> 6/4
1.500000
as expected.

in calc.y: add a second define:
%{
#include <stdio.h>
#define YYSTYPE float
#define YYSTYPE_IS_DECLARED
%}
And then..
./calc
-> 1/3
0.333333

Your proposal, and its correction by #Michael, does not work because the #define YYSTYPE is not propagated to the scanner. The %{ %} block is solely for bison (well, for the generated parser), it is not exported in the generated header. Read the documentation about %code to see what needs to be done: http://www.gnu.org/software/bison/manual/bison.html#g_t_0025code-Summary. In your case, %code requires is appropriate:
%code requires
{
# include <stdio.h>
# define YYSTYPE float
# define YYSTYPE_IS_DECLARED
}
It is easy to see what is going wrong once you equipped your parser with debug actions:
%debug
%printer { fprintf(yyoutput, "%f", $$); } <>
and
int main(int argc, char **argv)
{
printf("-> ");
yydebug = !!getenv("YYDEBUG");
yyparse();
return 0;
}
You'll see:
Reading a token: -> 1+2
Next token is token NUMBER (0.000000)
Shifting token NUMBER (0.000000)
Entering state 3
Reducing stack by rule 6 (line 28):
$1 = token NUMBER (0.000000)
-> $$ = nterm MD_result (0.000000)
Stack now 0 1
Entering state 5
Reading a token: Next token is token ADD (0.000000)
Reducing stack by rule 3 (line 22):
$1 = nterm MD_result (0.000000)
-> $$ = nterm AS_result (0.000000)
Stack now 0 1
Entering state 4
Next token is token ADD (0.000000)
Shifting token ADD (0.000000)
Entering state 6
Reading a token: Next token is token NUMBER (0.000000)
Shifting token NUMBER (0.000000)
Entering state 3
Reducing stack by rule 6 (line 28):
$1 = token NUMBER (0.000000)
-> $$ = nterm MD_result (0.000000)
Stack now 0 1 4 6
Entering state 11
Reading a token: Next token is token EOL (0.000000)
Reducing stack by rule 4 (line 23):
$1 = nterm AS_result (0.000000)
$2 = token ADD (0.000000)
$3 = nterm MD_result (0.000000)
-> $$ = nterm AS_result (0.000000)
which shows that when I type in "1+2", it actually sees 0.00000 about everywhere.
Now, how come it "works" for division? By accident, because float division and int division are very alike at the bit level. Toy with the following program which repeats the mistake: fill variables as integers, but use them as floats.
#include <stdio.h>
union YYSTYPE
{
int ival;
float fval;
};
#define TRY(L, O, R) \
do { \
union YYSTYPE lhs, rhs, res; \
lhs.ival = L; \
rhs.ival = R; \
res.fval = lhs.fval O rhs.fval; \
fprintf (stdout, "d. %d %s %d => %f\n", \
lhs.ival, #O, rhs.ival, res.fval); \
fprintf (stdout, "x. %x %s %x => %x\n", \
lhs.ival, #O, rhs.ival, res.ival); \
} while (0)
int main()
{
TRY(1, /, 2);
TRY(1, *, 2);
TRY(1, -, 2);
TRY(1, +, 2);
return 0;
}
But then, of course, the right answer is not to use #define YYSTYPE, which is way too coarse grained, but to use %union, as #Michael suggested.

Related

Bison is always giving me a yyerror and yyparse() is always returning 1

I am constantly getting yyerror : syntax error no matter the input file and yyparse() is always returning 1. I am having trouble finding what the issue is. I believe my BNF and input should be correct but I just keep getting this error and its driving me crazy.
%{
#include <stdio.h>
int yylex(void);
int yyerror(char *);
%}
%token LEFTPAREN RIGHTPAREN ASSIGNMENT SEMICOLON IF THEN ELSE BEGIN END WHILE
%token DO PROGRAM VAR AS INT BOOL WRITEINT READINT NUMBER LITERAL
%token OP2 OP3 OP4 IDENTIFIER
%start program
%%
program : PROGRAM declerations BEGIN statementSequence END
;
declerations : VAR IDENTIFIER AS type SEMICOLON declerations |
;
type : INT | BOOL
;
statementSequence : statement SEMICOLON statementSequence |
;
statement : assignment | ifStatement | whileStatement | writeInt
;
assignment : IDENTIFIER ASSIGNMENT expression | IDENTIFIER ASSIGNMENT READINT
;
ifStatement : IF expression THEN statementSequence elseClause END
;
elseClause : ELSE statementSequence |
;
whileStatement : WHILE expression DO statementSequence END
;
writeInt : WRITEINT expression
;
expression : simpleExpression | simpleExpression OP4 simpleExpression
;
simpleExpression : term OP3 term | term
;
term : factor OP2 factor | factor
;
factor : IDENTIFIER | NUMBER | LITERAL | LEFTPAREN expression RIGHTPAREN
;
%%
int yyerror(char *s) {
printf("yyerror : %s\n",s);
}
int main(){
printf("%d\n", yyparse());
return 0;
}

Flex & Bison: "true" being interpreted as and ID

I am writting a parser and a scanner in Ubuntu OS. In my flex code "scanner.l" I have an IDENTIFIER token and BOOL_LITERAL token. IDENTIFIER is any word and BOOL_LITERAL is either true or false.
In my bison code "parser.y" I have the grammar in which it should be able to take a BOO_LITERAL through the primary production.
However, the code is not working as intended. Here is the erro
Here are all of my files:
scanner.l
%{
#include <string>
#include <vector>
using namespace std;
#include "listing.h"
#include "tokens.h"
%}
%option noyywrap
ws [ \t\r]+
comment (\-\-.*\n)|\/\/.*\n
line [\n]
digit [0-9]
int {digit}+
real {int}"."{int}([eE][+-]?{digit})?
boolean ["true""false"]
punc [\(\),:;]
addop ["+""-"]
mulop ["*""\/"]
relop [="/=">">=""<="<]
id [A-Za-z][A-Za-z0-9]*
%%
{ws} { ECHO; }
{comment} { ECHO; nextLine();}
{line} { ECHO; nextLine();}
{relop} { ECHO; return(RELOP); }
{addop} { ECHO; return(ADDOP); }
{mulop} { ECHO; return(MULOP); }
begin { ECHO; return(BEGIN_); }
boolean { ECHO; return(BOOLEAN); }
end { ECHO; return(END); }
endreduce { ECHO; return(ENDREDUCE); }
function { ECHO; return(FUNCTION); }
integer { ECHO; return(INTEGER); }
real { ECHO; return(REAL); }
is { ECHO; return(IS); }
reduce { ECHO; return (REDUCE); }
returns { ECHO; return(RETURNS); }
and { ECHO; return(ANDOP); }
{boolean} { ECHO; return(BOOL_LITERAL); }
{id} { ECHO; return(IDENTIFIER);}
{int} { ECHO; return(INT_LITERAL); }
{real} { ECHO; return(REAL_LITERAL); }
{punc} { ECHO; return(yytext[0]); }
. { ECHO; appendError(LEXICAL, yytext); }
%%
parser.y
%{
#include <string>
using namespace std;
#include "listing.h"
int yylex();
void yyerror(const char* message);
%}
%error-verbose
%token INT_LITERAL REAL_LITERAL BOOL_LITERAL
%token IDENTIFIER
%token ADDOP MULOP RELOP ANDOP
%token BEGIN_ BOOLEAN END ENDREDUCE FUNCTION INTEGER IS REDUCE RETURNS REAL
%%
function:
function_header optional_variable body ;
function_header:
FUNCTION IDENTIFIER RETURNS type ';' ;
parameters:
parameters ',' |
parameter ;
parameter:
IDENTIFIER ':' type |
;
optional_variable:
variable |
;
variable:
IDENTIFIER ':' type IS statement_ ;
type:
INTEGER |
BOOLEAN |
REAL ;
body:
BEGIN_ statement_ END ';' ;
statement_:
statement ';' |
error ';' ;
statement:
expression |
REDUCE operator reductions ENDREDUCE ;
operator:
ADDOP |
MULOP ;
reductions:
reductions statement_ |
;
expression:
expression ANDOP relation |
relation ;
relation:
relation RELOP term |
term;
term:
term ADDOP factor |
factor ;
factor:
factor MULOP primary |
primary ;
primary:
'(' expression ')' |
INT_LITERAL |
REAL_LITERAL |
BOOL_LITERAL |
IDENTIFIER ;
%%
void yyerror(const char* message)
{
appendError(SYNTAX, message);
}
int main(int argc, char *argv[])
{
firstLine();
yyparse();
lastLine();
return 0;
}
Other associated files:
listing.h
enum ErrorCategories {LEXICAL, SYNTAX, GENERAL_SEMANTIC, DUPLICATE_IDENTIFIER,
UNDECLARED};
void firstLine();
void nextLine();
int lastLine();
void appendError(ErrorCategories errorCategory, string message);
listing.cc
#include <cstdio>
#include <string>
using namespace std;
#include "listing.h"
static int lineNumber;
static string error = "";
static int totalErrors = 0;
static void displayErrors();
void firstLine()
{
lineNumber = 1;
printf("\n%4d ",lineNumber);
}
void nextLine()
{
displayErrors();
lineNumber++;
printf("%4d ",lineNumber);
}
int lastLine()
{
printf("\r");
displayErrors();
printf(" \n");
return totalErrors;
}
void appendError(ErrorCategories errorCategory, string message)
{
string messages[] = { "Lexical Error, Invalid Character ", "",
"Semantic Error, ", "Semantic Error, Duplicate Identifier: ",
"Semantic Error, Undeclared " };
error = messages[errorCategory] + message;
totalErrors++;
}
void displayErrors()
{
if (error != "")
printf("%s\n", error.c_str());
error = "";
}
makeile
compile: scanner.o parser.o listing.o
g++ -o compile scanner.o parser.o listing.o
scanner.o: scanner.c listing.h tokens.h
g++ -c scanner.c
scanner.c: scanner.l
flex scanner.l
mv lex.yy.c scanner.c
parser.o: parser.c listing.h
g++ -c parser.c
parser.c tokens.h: parser.y
bison -d -v parser.y
mv parser.tab.c parser.c
mv parser.tab.h tokens.h
listing.o: listing.cc listing.h
g++ -c listing.cc
Note:
I have to run "makeile", "bison -d parser.y" and finally "makefile" again. Then, I run the following command "./compile < incremental1.txt" and I get the following error:
enter image description here
Please help me understand why I am getting a syntax error.
#SoronelHaetir has certainly identified one of the problems with your parser. But that problem cannot create the syntax error message which appears in your image. [Note 1] Your grammar allows identifiers in exactly the same place as boolean literals, so the fact that true is actually scanned as an identifier will not produce a syntax error in an expression which starts true and. (In other words, x and... would be parsed just the same.)
The problem is actually your use of 8.E+1 as a numeric literal. Your rule for REAL_LITERAL uses the pattern
{int}"."{int}([eE][+-]?{digit})?
which doesn't match 8.E+1 because there is no {int} followed the .. So when the scanner reaches the input 8.E+1, it produces the INT_LITERAL 8, which is the longest match. When it is asked for the next token, it first sees a ., but that doesn't match any pattern so it uses the default fallback action (ECHO), and then continues to the next character (E) which matches the IDENTIFIER pattern. And the input
true and 8 E ...
is indeed a syntax error: there is an unexpected identifier following the 8, and that's what bison reports.
Aside from fixing the pattern for real literals, you should make sure that you do something sensible with unrecognised characters; flex's default action -- which basically just ignores characters that can't match any pattern -- is not of much use, particularly in debugging (as I think the above explanation demonstrates).
There are a number of other issues with your patterns involving the same misconception about the syntax of character classes as shown in the boolean literal pattern. This indicates to me that you did not attempt to test your lexical scanner before hooking it into your parser. That's an essential step in writing parsers; if your lexical scanner is not returning the tokens you expect it to return, you're going to have a lot of trouble trying to figure out what errors there might be in your grammar.
You might find the debugging techniques outlined in this answer useful. (That post also has links to the flex and bison manuals. Section 6 of the flex manual is a brief but complete guide to the syntax of flex patterns, and you might want to take a few minutes to read it.)
Notes
Please copy and paste the text of error messages into your questions rather than using an image showing a screenshot. Images are very hard to read on smartphones, for example, or for people who rely on screen-readers. And it's not possible to copy a part of a screenshot into an answer, which I would have preferred to have done here.
Your boolean pattern should be "true"|"false" not ["true""false"].
Honestly, the way your patterns are set up is just weird. Is there some reason not to use:
...
%%
"true" { /* */ return BOOL_LITERAL; }
"false { /* */ return BOOL_LITERAL; }
Patterns make sense when you aren't trying to match literals but here you are.

Undefined reference to 'yylex' bison error

Hi I am new to bison and flex and I am trying to create a simple calculator however I seem to be having errors when trying to compile.
The following is my flex .l file (named a.l):
%{
#include "a.tab.h"
%}
number [0-9]+
%%
"+" {return ADD;}
"-" {return SUB;}
"*" {return MUL;}
"/" {return DIV;}
"|" {return ABS;}
{number} { return NUMBER;}
\n {return EOF;}
[ \t] { }
. {printf("Mystery Character %s\n", yytext); }
%%
and the following is my bison .y file(named a.y):
%{
#include <stdio.h>
int yyparse(void);
%}
%token NUMBER ADD SUB MUL DIV ABS EOL
%%
calclist: /*nothing*/ | calclist exp EOL { printf("=%d\n, $1") };
exp: factor
| exp ADD factor { $$ = $1 + $3; }
| exp SUB factor { $$ = $1 - $3; }
;
factor: term |
| factor MUL term { $$ = $1 * $3; }
| factor DIV term { $$ = $1 / $3; }
term: NUMBER
| ABS term { $$ = $2 >= 0? $2 : - $2; }
;
%%
int main(void)
{
return(yyparse());
}
void yyerror(char *s)
{
fprintf(stderr, "Error : Exiting %s\n", s);
}
This is what I write in the console:
flex a.l
bison a.y
gcc a.tab.c -lfl -o a.exe
The error I get is:
a.tab.c:(.text+0x1f2): undefined reference to `yylex'
collect2.exe: error: ld returned 1 exit status
I also get the following warnings:
a.tab.c: In function 'yyparse':
a.tab.c:595:16: warning: implicit declaration of function 'yylex' [-Wimplicit-function-declaration]
# define YYLEX yylex ()
^
a.tab.c:1240:16: note: in expansion of macro 'YYLEX'
yychar = YYLEX;
^~~~~
a.tab.c:1396:7: warning: implicit declaration of function 'yyerror' [-Wimplicit-function-declaration]
yyerror (YY_("syntax error"));
^~~~~~~
a.y: At top level:
a.y:32:6: warning: conflicting types for 'yyerror'
void yyerror(char *s)
^~~~~~~
a.tab.c:1396:7: note: previous implicit declaration of 'yyerror' was here
yyerror (YY_("syntax error"));
^~~~~~~
Would anybody be able to explain to me why these errors/warnings may be occuring?
There will be two generated C files, one generated by flex and one by bison. The one created by flex will be called "lex.yy.c" and you'll need to compile that one as well.

Unexpected behavior from lexer and grammar for simple calculator

I'm starting on the whole world of Flex and Bison. So I followed a tutorial to write this l file for flex:
%{
#include <stdio.h>
#include <stdlib.h>
void yyerror(char *);
#include "y.tab.h"
%}
%%
/******************** RULES ********************/
/* One letter variables */
[a-z] {
yylval = *yytext - 'a'; // This is to return a number between 0 and 26 representting the letter variable.
printf("VAR: %s\n",yytext);
return VARIABLE;
}
/* Integer constants */
[0-9]+ {
yylval = atoi(yytext);
printf("INT: %d\n",yylval);
return INTEGER;
}
/* Operators */
[-+()=/*\n]+ { printf("OPR: %s\n",yytext); return *yytext; /*\n is considered an operator because it signals the end of a statement*/ }
/* This skips white space and tab chararcters */
[ \t] ;
/* Anything esle is not allowed */
. yyerror("Invalid character found");
/***************** SUBROUTINES *****************/
%%
int yywrap(void){
return 1;
}
And this is the grammar:
/***************** DEFINITIONS *****************/
%token INTEGER VARIABLE
%left '+' '-'
%left '*' '/'
%{
void yyerror(char *);
int yylex(void);
int sym[26];
%}
%%
/******************** RULES ********************/
program:
program statement '\n'
|
;
statement:
expr { printf("EXPR: %d\n", $1); }
| VARIABLE '=' expr { sym[$1] = $3; }
;
expr:
INTEGER
| VARIABLE { $$ = sym[$1]; }
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| '(' expr ')' { $$ = $2; }
;
%%
/***************** SUBROUTINES *****************/
void yyerror(char *s){
printf("%s\n",s);
}
int main(void) {
yyparse();
return 0;
}
And serveral question arise. The first comes when compiling. This is how I compile:
bison -d bas.y -o y.tab.c
flex bas.l
gcc y.tab.h lex.yy.c y.tab.c -o bas_fe
Which gives me two warnings like this:
bas.y:24:7: warning: incompatible implicit declaration of built-in function ‘printf’
expr { printf("EXPR: %d\n", $1); }
^
bas.y: In function ‘yyerror’:
bas.y:39:4: warning: incompatible implicit declaration of built-in function ‘printf’
printf("%s\n",s);
Now, they are warnings and the print work, but I found it odd, since I have clearly included the libraries for use of the printf function.
My real question arises from my interaction with the program. This is the console output:
x = (3+5)
VAR: x
OPR: =
OPR: (
INT: 3
OPR: +
INT: 5
x
OPR: )
VAR: x
syntax error
Several questions arise from this.
1) Upon inputting x = (3+5) the program printout does not include the ')' Why?
2) When inputting x (expected output would have been 8) only then the ')' appears. Why?
3) And then there is the "syntax error" message. I'm assuming the message is automatically generated within the code of y.tab.c. Can it be changed to somthing more meaningful? Am I right in assuming that the syntax error is because the program found ) and newline and the variable and that this DOES NOT correspond to a program statement, as defined by the grammar?
I have clearly included the libraries for use of the printf function.
You included stdio.h in your flex file, but not in your bison file. And the warnings about printf being undeclared are from your bison file, not your flex file.
When you compile multiple files with gcc (or any other C compiler), the files are compiled independently and then linked together. So your command
gcc y.tab.h lex.yy.c y.tab.c -o bas_fe
does not concatenate the three files and compile them as a single unit. Rather, it compiles the three files independently, including uselessly compiling the header file y.tab.h.
What you should do is add a prolog block including #include <stdio.h> to your bas.y file.
[-+()=/*\n]+ {... return *yytext; ...}
This flex pattern matches any number of characters from the set [-+()=/*\n]. So in the input x=(3+5)\n, the )\n is being matched as a single token. However, the action returns *yytext, the first character of yytext, effectively ignoring the \n. Since your grammar requires \n, that creates a syntax error.
Simply remove the repetition operator from the pattern.
Can the error message be changed to something more meaningful?
If you have a reasonably modern bison, add the declaration
%error-verbose
to the beginning of your bison file.

Errors When Using Bison

Now I'm getting other things. When I do a bison -d calc.y I'm getting many source codes in the console (with many m4_define), but it doesn't generate any file. Now my code is like this:
%{
#define YYSTYPE double
#include <math.h>
%}
%token NUM
%%
input: /* empty */
| input line
;
line: '\n'
| exp '\n' { printf ("\t%.10g\n", $1); }
;
exp: NUM { $$ = $1; }
| exp exp '+' { $$ = $1 + $2; }
| exp exp '-' { $$ = $1 - $2; }
| exp exp '*' { $$ = $1 * $2; }
| exp exp '/' { $$ = $1 / $2; }
/* Exponentiation */
| exp exp '^' { $$ = pow ($1, $2); }
/* Unary minus */
| exp 'n' { $$ = -$1; }
;
%%
/* Lexical analyzer returns a double floating point
number on the stack and the token NUM, or the ASCII
character read if not a number. Skips all blanks
and tabs, returns 0 for EOF. */
#include <ctype.h>
#include <stdio.h>
yylex ()
{
int c;
/* skip white space */
while ((c = getchar ()) == ' ' || c == '\t')
;
/* process numbers */
if (c == '.' || isdigit (c))
{
ungetc (c, stdin);
scanf ("%lf", &yylval);
return NUM;
}
/* return end-of-file */
if (c == EOF)
return 0;
/* return single chars */
return c;
}
yyerror (s) /* Called by yyparse on error */
char *s;
{
printf ("%s\n", s);
}
main ()
{
yyparse ();
}
Original Question
I'm trying to create my own development language, but it's so hard to start and as I'm starting, I'm getting many errors and I don't know how to solve the. This is my code:
#include <ctype.h>
#include <stdio.h>
yylex ()
{
int c;
/* skip white space */
while ((c = getchar ()) == ' ' || c == '\t')
;
/* process numbers */
if (c == '.' || isdigit (c))
{
ungetc (c, stdin);
scanf ("%lf", &yylval);
return NUM;
}
/* return end-of-file */
if (c == EOF)
return 0;
/* return single chars */
return c;
}
main ()
{
yyparse ();
}
The calc.y source code file:
%token NUM
%%
input:
| input line
;
line: '\n'
| exp '\n' { printf ("\t%.10g\n", $1); }
;
exp: NUM { $$ = $1; }
| exp exp '+' { $$ = $1 + $2; }
| exp exp '-' { $$ = $1 - $2; }
| exp exp '*' { $$ = $1 * $2; }
| exp exp '/' { $$ = $1 / $2; }
/* Exponentiation */
| exp exp '^' { $$ = pow ($1, $2); }
/* Unary minus */
| exp 'n' { $$ = -$1; }
;
%%
And now the compiler log:
C:\Documents and Settings\Nathan Campos\Desktop>gcc calc.tab.c -lm -o rpcalc
calc.tab.c: In function `yylex':
calc.tab.c:15: error: `yylval' undeclared (first use in this function)
calc.tab.c:15: error: (Each undeclared identifier is reported only once
calc.tab.c:15: error: for each function it appears in.)
calc.tab.c:16: error: `NUM' undeclared (first use in this function)
What is wrong?
Revised answer
The amended code you provide compiles almost cleanly - you should #include <stdio.h> so that printf() is declared before it is used. (You should also use prototypes for functions - such as yyerror(const char *str), and generally drag the code into the 21st Century.)
It even responds correctly to '1 2 +'.
With a single file, you don't need to use 'bison -d'.
If you are seeing garbage, you need to review your build commands and build environment.
Original answer
Where to begin?
Recommendation: get hold of the O'Reilly book on Lex and Yacc (from the library) or Flex and Bison (an August 2009 update/rewrite - probably not in the library yet). If you need a resource quicker, then I suggest the Unix Version 7 manuals or the GNU Bison manual - both of which are available online. In particular, read the 7th edition documents on Lex and Yacc; you're not trying to do what wasn't covered in the original decriptions (though the C code there pre-dates the C89 standard by a decade or more).
You need to use bison -d to generate a header containing the token numbers. For source file 'zzz.y', this will generate C code 'zzz.tab.c' and 'zzz.tab.h'.
You need to include 'zzz.tab.h' in the main program.
You need to use C99 and should, therefore, have a return type on yylex() and main().
You need to declare yylval. Fortunately, the Bison 'zzz.tab.h' file will do that correctly; it isn't quite as simple as it appears.
You may want to allow for negative numbers in your lexical analyzer (-3.1416). You may want to allow for explicitly positive numbers too (+3.1416).
You probably need to ensure that '$$' and friends are of type double rather than the default type of int (#define YYSTYPE double).
IIRC, yylval is declared by Bison, but you have to supply the type. Without that, the compiler gets confused and can give misleading errors.
You need to define YYSTYPE. In your case, you may get away with "#define YYSTYPE double". Do this in the grammar, in a %{ ... %} block near the top.
%union is also available for declaring YYSTYPE as a union.
This looks like the Bison manual standard rpcalc example, so I'll assume you can look up "YYSTYPE" and "%union" easily enough.
In your .y file add these lines:
void yyerror(char *errorinfo);
int yylex(void);
You'll also need to define your token types as generated by flex:
%token NUM
and so on.
Edit: Flex and Bison (O'Reilly) is a great resource.
You have not declared the variable yylval anywhere.
It is not a good idea to #define YYSTYPE. It certainly doesn't work with the Bison I tried it with. What you should do is to tell Bison that the values you work with are doubles:
%union {
double dval;
}
%type <dval> exp NUM
Bison will now generate an appropriate YYSTYPE for you.
But I recommend that you look at a tutorial or something. Thomas Niemann's
A Compact Guide to Lex & Yacc
is a good one, giving examples and step-by-step explanations.
I teach a compiler course, and my experience is that Bison, and grammars, can be difficult to get started with by too much of trial-and-error.

Resources