[Solved]Goal Exercise Acquaint Two Powerful Tools Generation Compilers Flex Bison Homework Files Q37190247
The goal of this exercise is to acquaint yourself with two verypowerful tools for the generation of compilers: flex and bison.In this homework files for a calculator application are provided toyou. The files are as the following list.
File
Description
calc.l
Contains the regular expression rules
calc.y
Contains the grammar rules
calc.h
Contains a data structure used by calculator
mymake
Contains the make commands to build the application
You need to transfer the files to a directory in your glaccount. The address of gl account is gl.umbc.edu. You need to usea FTP application to transfer the files.
The following command builds the calculator application:
[user@linux2] make -f mymake calc
After building the application you can run the executable filecalc which is created in the folder. The following examplepresents a session of running the calculator. At the prompt ofcalculator user can enter any arithmetic expression and by pressingenter the calculator evaluates the arithmetic expression. The exitcommand is dot, and by typing ? character user can get helpinstructions on the calculator prompt.
[user@linux2] calc >> 3 + 4
7
>> .
[user@linux2]
Your job is to modify the application to add logical operatorsas in the following table. All operators will have leftassociativity.
1
Operator
Meaning
Precedence
Description
&
Logical and
Lowest
This is equivalent to && in C language. It is a binaryoperator. If it evaluates to true, it returns 1 and if evaluates tofalse it returns 0.
|
Logical or
Same as &
This is equivalent to || in C language. It is a binary operator.If it evaluates to true, it returns 1 and if evaluates to false itreturns 0.
==
Equal
Higher than & and |, lower than >
It is a binary operator. If both sides are of equal values, itreturns 1, otherwise it returns 0.
>
Greater than
Highest
It is a binary operator. If left operand has a greater valuethan right operand, it returns 1, otherwise it returns 0.
The following is an example test session that your applicationcan be tested against. You need to test your modifications for allfour operators you have added.
>> a = 5 >> b = 8 >> a > b 0
You need to submit your modified files, i.e. calc.l and calc.ythrough the submit utility on your gl account.
Hints:
-
● In this application you do not need to modify the grammarrules to implement associativity and precedence of operators. Theycan be defined for bison, andbison will implement them.
-
● In the declaration section of calc.y you can define theprecedence and associativity of operators. The precedence andassociativity of arithmetic operators are already defined in thisfile. You can define this information for your logical operators inthe same place and in the same way.
-
● Logical and (&) has a higher precedence than assignment(=) operator, and Greater than (>) has a lower precedence than +and – operators
CALC.H
/* SYMBOLTABLESIZE is the maximum number of sysbols we can have */#define SYMBOLTABLESIZE 20/* An entry in the symbol table has a name, a pointer to a function, and a numeric value. */struct symtab { char *name; double (*funcptr)(); double value;} symtab[SYMBOLTABLESIZE];struct symtab *symlook();void printHelp();void yyerror();
CALC.Y
%{
#include “calc.h”
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
/************************************************************************
* Defines a yacc grammar for a simple calculator using infix
* notation. WHen executed, the calculator enters a loop in
* which it prints the prompt >>, reads a toplevelexpression
* terminated by a newline, and prints its value. Operators
* include +, -, *, and = (assignment). Note that all
* expressions return values, even assignment. Parentheses
* can be used to override operator precedence and
* associativity rules. Based on zcalc by ruiz@capsl.udel.edu
************************************************************************/
int yylex();
int yyparse();
%}
/*
Th union directive specifies the collection of tpes ourgrammar
deals with — just doubles and pointers to symbol tableentries.
*/
%union {
double dval;
struct symtab *symp;
}
/*
Declare the token types and any associated value types. Wemade
EQ a token in calc.l because otherwise ‘=’ and ‘==’ wouldclash.
*/
%token <symp> NAME
%token <dval> NUMBER
/* The folowing declarations specify the precidence andassociativity
of our operators. The operators -, +, * and / to beleft
associative, * and EQ to be right associative andUMINUS to be
non-associative (since it is a unary operator). The’=’ operator
has the lowest precedence and UMINUS thehighest.
*/
%right ‘=’ /*lowest precedence*/
%left ‘-‘ ‘+’
%left ‘*’ ‘/’
%nonassoc UMINUS /* highest precedence */
/*
Declare the type of expression to be a dval (double).
*/
%type <dval> expr
%%
/*
Here are our grammar rules. a session is a sequence of lines.A
toplevel is just an expr (print its value followed by two
newlines and the prompt >>) or a ‘? (print help) or a ‘.'(exit).
An expr can be a number, name, the sum of two exprs, …
*/
session: /* empty */
|
session toplevel ‘n’
;
toplevel: expr { printf(“%gnn>> “, $1); }
| ‘?’ { printHelp(); printf(“n>> “); }
| ‘.’ { printf(“Exiting 331 calcn”); exit(1); }
;
expr: NUMBER { $$ = $1; }
| NAME { $$ = $1->value; }
| NAME ‘=’ expr { $1->value = $3; $$ = $3; }
| expr ‘+’ expr { $$ = $1 + $3; }
| expr ‘-‘ expr { $$ = $1 – $3; }
| expr ‘*’ expr { $$ = $1 * $3; }
| expr ‘/’ expr { $$ = $1 / $3; }
| ‘-‘ expr %prec UMINUS { $$ = -$2; }
| ‘(‘ expr ‘)’ { $$ = $2; }
;
%%
struct symtab *
symlook(s)
char *s;
{
char *p;
struct symtab *sp;
/* given the name of a symbol, scan the symboltable and
either return the entry with matching name or add it
to the next free cell in the symbol table. */
for(sp = symtab; sp <&symtab[SYMBOLTABLESIZE]; sp++) {
/* If the symbol table entry has a name and itsequal
to the one we are looking for, return this entry */
if (sp->name && !strcmp(sp->name,s))
return sp;
/* If the name is empty then this entry is free, sothe
symbol must not be in the table and we can add it here
and return this entry. */
if (!sp->name) {
sp->name = strdup(s);
return sp;
}
}
/* We searched the entire symbol table and neitherfound
the symbol or an unused entry. So the table must be
full. Sigh. */
yyerror(“The symbol table is full,sorry…n”);
exit(1);
}
void printHelp()
{ /* print calculator help and return */
printf(“Enter an expression in infix notation followed by anewline.n”);
printf(“Operators include +, -, * and =. Defined functionsincluden”);
printf(“sqrt, exp and log. You can assign a variable using the=n”);
printf(“operator. Type . to exit. Syntax errors will terminatethen”);
printf(“program, so be careful.n”);
}
/* If error prints error and Do not accept to signify bad syntaxin
program */
void yyerror(char *msg) /* yacc error function */
{
printf(“%s n” , msg);
}
int yywrap(){return 1;}
int main()
{ /* print herald and call parser */
printf(“331 Calculatorn(type ? for help and . toexit)nn>> “);
yyparse();
return 0;
}
CALC.L
%{
#include “y.tab.h”
#include “calc.h”
#include <math.h>
/************************************************************************
A lexical scanner to recognize numbers, symbols and the EQ
operator. When a NUMBER is found, its value is set is set tothe
appropriate float. When a NAME is found, an entry in symboltable is
created (with initial value 0.0) and the token’s value is apointer to
this entry. If a ‘==’ sequence is seen, it is returned as atoken
EQ. Spaces and tabs are ignored. Any other characters,including
a newline, are passed on as their own tokens. Based on thezcalc
calculator by ruiz@capsl.udel.edu
************************************************************************/
%}
D [0-9]
A [a-zA-Z]
AD [a-zA-Z0-9]
%%
({D}+|({D}*.{D}+)([eE][-+]?{D}+)?) {yylval.dval = atof(yytext);return NUMBER;}
{A}{AD}* {struct symtab *sp = symlook(yytext); yylval.symp = sp;return NAME;}
[ t] ;
n |
. return yytext[0];
%%
MYMAKE
# A Makefile for simple lex and yacc examples
# Comment out the proper lines below according to the scannerand
# parser generators available in your system
#LEX = lex
#YACC = yacc -d
LEX = flex
YACC = bison -d -o y.tab.c
# We assume that your C-compiler is called cc
# CC = cc -m32
# calc is the final object that we will generate, it is producedby
# the C compiler from the y.tab.o and from the lex.yy.o
calc: y.tab.o lex.yy.o
$(CC) -o calc y.tab.o lex.yy.o
# These dependency rules indicate that (1) lex.yy.o dependson
# lex.yy.c and y.tab.h and (2) lex.yy.o and y.tab.o depend oncalc.h.
# Make uses the dependencies to figure out what rules must berun when
# a file has changed.
lex.yy.o: lex.yy.c y.tab.h
lex.yy.o y.tab.o: calc.h
## This rule will use yacc to generate the files y.tab.c andy.tab.h
## from our file calc.y
y.tab.c y.tab.h: calc.y
$(YACC) -v calc.y
## this is the make rule to use lex to generate the filelex.yy.c from
## our file calc.l
lex.yy.c: calc.l
$(LEX) calc.l
## Make clean will delete all of the generated files so we canstart
## from scratch
clean:
-rm -f *.o lex.yy.c *.tab.* calc *.output
Expert Answer
Answer to The goal of this exercise is to acquaint yourself with two very powerful tools for the generation of compilers: flex … . . .
OR

