CSCI 400
Bison simpleCalc Intro Exercise
- Download simpleCalc.y and simpleCalc.l
- Create calculator program:
- bison -d simpleCalc.y
- flex -L -osimpleCalc.c simpleCalc.l
- gcc -c simpleCalc.c
- gcc -c simpleCalc.tab.c
- gcc -Lc:\progra~1\gnuwin32\lib simpleCalc.o simpleCalc.tab.o
-osimpleCalc.exe -lfl –ly
- As a convenience, you can use the batch file mbison.bat
instead of typing all the above:
- Andy Niccolai provided this makefile for *nix.
- Aaron LeBahn provided this mbison script for *nix.
- Test with valid sentences (e.g., 3+6-4) and invalid sentences.
- Read and try to understand simpleCalc.l and simpleCalc.y.
If you have questions, see the slides in the PowerPoint. More
questions - Ask!
- Do the exercises described below. You can put all the
exercises in one file.
Downloads
If you want to use Flex and Bison on your own computer you can find
free downloads for Windows at:
Flex:
http://gnuwin32.sourceforge.net/packages/flex.htm
Bison:
http://gnuwin32.sourceforge.net/packages/bison.htm
gcc: http://sourceforge.net/projects/gcw/
Or do a search to find versions for other OSs. For Windows
environments you will probably need to add flex and bison to your
PATH. This varies based on version of Windows, but for many the
Path is available via the Control Panel. I am not sure the
version of gcc above is the same one I used or that is installed in
CTLM. Another option is to download the Dev C++ IDE, which should
also install a gcc compiler on your system. That's what I did
originally.
Exercises
Exercise #1:
Once you have gotten the simpleCalc program to run, change it to handle
+ and * with correct precedence using the grammar with terms and
factors presented in chapter 4 of text:
Expr -> Expr + Term
| Term
Term -> Term * Factor
| Factor
Factor -> (Expr)
| NUMBER
Exercise #2:
Now change simpleCalc.l to accept floating point values OR integers.
- Remove
extern int yylval;
(yylval is no longer
simply an int)
- you will create a union in simpleCalc.y. Use the name of that
union in
simpleCalc.l, for example
yylval.ival = atoi(yytext);
would be used to
set a named union of ival to an integer value.
- use
atof
for the floating point value
- Modify
#include simpleCalc.tab.h
if you change the
name of your
file. For example, I named my file simpleCalcEx2 so I did:
#include simpleCalcEx2.tab.h
Details to change simpleCalc.y to accept floating point values (char*
will be needed later):
- Create a union, example:
%union {
float fval;
int ival;
char *sval;
}
The union belongs in the declaration
section of the .y file, above/before the token and type declarations.
- Define the "data types" for your variables. Every token
returned from the .l file should have a %token statement. Every
non-terminal in your .y files should have a %type
statement. For example:
%token <ival> NUMBER
%type <fval> expression
- Update your Factor rule to accept NUMBER or a floating point type
of number
(e.g., FNUMBER). In other words, you will have two grammar rules,
one which expects an integer (NUMBER) and one which expects a float
(FNUMBER).
- The printf in statement: needs to print a floating point value:
{ printf("= %f\n", $1);
}
Exercise #3:
Update simpleCalc to accept statements like @myVar = 3.4*4
Output will be: myVar = 13.6
- Purpose:
- using a C-function as part of lexer to preprocess yytext
before setting yylval. Specifically, we will be removing the @ from the
front of the variable name. Why? Just to see how to
preprocess lexemes. Other uses for this type of preprocessing
might be to convert symbols to lower case or to remove quotation marks
from around quoted strings.
- Steps in simpleCalc.l:
- add prototype in the definition section for a function named
extract_name
.
The
parameter
to
this
function is a char* (you will pass in yytext). You
can either return a char* or just modify the parameter, since it’s an
array. Put the prototype in declaration section, between the %{ and
%}
- add function
extract_name
to the C section. This function
will
just remove the @ from the front of the variable name. HINT: remember
that c strings end in ‘\0’. This can be used to control
your loop. Be sure the string you return includes the '\0'.
- When you have recognized a variable (@ followed by upper or
lower case letters, in our simple example),
- if you return a char* you will set
yylval.sval
=
extract_name(yytext);
- IMPORTANT: if you modified the parameter, call extract_name
the use
strdup to pass yytext to bison:
extract_name(yytext);
yylval.sval =
strdup(yytext);
- If you do not use strdup you may have more characters than
you desire in your variable name.
- Remember to return NAME (or whatever you called your token)
- Steps in simpleCalc.y:
- Be sure you still have NAME = expression in your grammar, and
add an action so it prints both the variable and the expression result.
- Declare NAME as a token of type sval (or whatever
name you
used in your union)
Exercise #4:
Update simpleCalc to accept a "program" of expressions. Example
program:
{
@myvar=1+2;
@anotherVar=2*3.5
}
- Purpose:
- Understand recursive language statements
- Understand the start symbol
- Steps in simpleCalc.l:
- You may want to put this exercise and #5 in a separate file. Otherwise,
you'll need to modify your program rule to allow a statement as well as
the program surrounded by braces (described below) or
have your program only accept an entire program, not a single statement.
- The current processing for \n (
\n
return 0;
) will not allow
multiple statements to be processed. We effectively want to skip
the \n in the input file. Notice the rule for tab (\t) does
nothing. You should do the same for \n. You may modify the
rule for \n OR add \n to the character class for whitespace.
- The rules for this exercise will be updated to expect '{' at
the beginning of the program and '}' at the end. You can define a
token for '{' and '}' if you like, OR you can simply be sure that
simpleCalc.l passes unrecognized characters to the rules. For the
latter option, be sure the following rule is included in the .l:
. return yytext[0];
- Steps in simpleCalc.y:
- Write a rule to recognize an entire program. This rule should be
the first one in the list, because the first non-terminal encountered
is considered the start symbol or goal
for your language.
program: '{' statements '}' { endProgram(); }
;
- Write a rule to allow multiple statements. This is
similar to the small Pascal-like language we studied in chapter
3:
statements: statement ';' statements
| statement
;
- Create the function called when a program has been
recognized. This function will simply print a message, such as
"Goodbye" and exit the program.
- You must put a prototype for this function in the
declarations section at the top of the .y file, between %{ and %}
- Put the function definition in the C-code section at the
bottom of the .y file. Be sure to have %% between the rule
section and the C-code section. This will be a very simple
function, such as:
void endProgram()
{
printf("Goodbye\n");
exit(0);
}
Exercise #5:
Update the program to determine the total value of all expressions in
your program. NOTE: This does not represent an actual calculator
or program, but is used to illustrate concepts that will be useful for
the homework.
- Purpose:
- See how to use global variables in the .y file
- See how to pass values to functions
- Steps in simpleCalc.l:
- Steps in simpleCalc.y:
- In the declarations section, inside the %{ and %}, declare a
variable of type float named total.
Initialize
the
value
to
0.
- Update endProgram() to display the total:
printf("Your total is: %f, Goodbye!\n", total);
- Call a function named updateTotal to add expression values to
your total. Be sure to add the prototype to the top of the
program and the function definition at the bottom:
void updateTotal(float value)
{
total += value;
}
Example of updating the rules (yours may vary):
statement: NAME '=' expression ';'
{ updateTotal($3); printf("%s = %f\n", $1, $3); }
| expression ';' { updateTotal($1); printf("= %f\n",
$1); }
;
Specific Requirements
This assignment is worth 10 points.
- (2) Correct precedence for * and +
- (2) Accept floats or ints
- (2) Allow variable name
- (2) Accept program of expressions
- (2) Calculate and display total
Submission:
Zip your .y and .l files and submit on Blackboard. If you worked with a
partner, be sure to include both names in the comments.