Indian Institute Of Information Technology Raichur
Compilers Principles, Techniques And Tools
Bison Exercises
Note→ Feel free to inform us, if you feel that assignment has somekind of error.
Q1.) Use YACC/Bison to Convert Binary to Decimal (including fractional numbers).
Flex code→
%{
#include "btd.tab.h" /*This header file name you have to change according to your file name*/
#include <stdlib.h>
#include <string.h>
%}
%%
[01]+ { yylval.str = strdup(yytext); return BINARY; }
"." { return DOT; }
\n { }
[ \t] { /* Ignore whitespace */ }
. { printf("Invalid character: %s\n", yytext); }
%%
int yywrap() { return 1; }
Bison Code→
%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
void yyerror(const char *s);
int yylex();
int binaryToDecimal(const char *binary);
double binaryToFloat(const char *intPart, const char *fracPart);
/*writng extern int yyval not required*/
%}
%union {
/*"By default, Bison treats tokens as int. However, since our tokens store char *, we must
explicitly define their type using %token <str>. If yyval always contained an int, then %union
would not be necessary."*/
char *str;
}
%token <str> BINARY
%type <str> binary
%%
input:
binary {
printf("DEBUG: Recognized integer binary: %s\n", $1);
printf("Decimal: %d\n", binaryToDecimal($1));
free($1);
}
| binary DOT binary {
printf("DEBUG: Recognized fractional binary: %s.%s\n", $1, $3);
printf("Decimal: %f\n", binaryToFloat($1, $3));
free($1);
free($3);
}
;
binary:
BINARY { $$ = $1; }
;
%%
int binaryToDecimal(const char *binary) {
int result = 0;
while (*binary) {
result = result * 2 + (*binary - '0');
binary++;
}
return result;
}
double binaryToFloat(const char *intPart, const char *fracPart) {
int intValue = binaryToDecimal(intPart);
double fracValue = 0.0;
double weight = 0.5; // 2^(-1)
for (const char *p = fracPart; *p; p++) {
if (*p == '1') {
fracValue += weight;
}
weight /= 2;
}
return intValue + fracValue;
}
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
printf("Enter a binary number (with or without a fraction):\n");
yyparse();
return 0;
}
Q2.) Use YACC/Bison to implement, evaluator for arithmetic expressions (Desktop calculator).
Flex Code→ Use YACC to implement, evaluator for arithmetic expressions (Desktop
calculator).
%{
#include "calc.tab.h" /*This header file name you have to change according to your file name*/
%}
%%
[0-9]+(\.[0-9]+)? { yylval.num = atof(yytext); return NUMBER; }
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"(" { return LPAREN; }
")" { return RPAREN; }
\n { return ENDL; }
[ \t] { }
. { printf("Invalid character: %s\n", yytext); }
%%
int yywrap() {
return 1;
}
Bison Code→
%{
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void yyerror(const char *s);
int yylex();
%}
%union {
double num;
}
%token <num> NUMBER
%token ADD SUB MUL DIV LPAREN RPAREN ENDL
%left ADD SUB
%left MUL DIV
%right UMINUS
%type <num> expr
%%
input:/*empty*/
| input expr ENDL {
printf("Result: %lf\n", $2);
}
;
expr: NUMBER { $$ = $1; }
| expr ADD expr { $$ = $1 + $3; }
| expr SUB expr { $$ = $1 - $3; }
| expr MUL expr { $$ = $1 * $3; }
| expr DIV expr {
if ($3 == 0) {
yyerror("Error: Division by zero!");
YYABORT;
}
$$ = $1 / $3;
}
| LPAREN expr RPAREN { $$ = $2; }
| SUB expr %prec UMINUS { $$ = -$2; }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
printf("Enter arithmetic expressions :\n");
yyparse();
return 0;
}
Q3.) Write a YACC/Bison “desk calculator” program that will evaluate Boolean expressions.
Note→ Do it by yourself, it’s kind of similar to the desktop calculator problem.
Test Case 1:
Input: T
Output: T
Test Case 2:
Input: F
Output: F
Test Case 3 (AND Operation)
Input: T && F
Output: F
Test Case 4 (OR Operation)
Input: T || F
Output: T
Test Case 5 (NOT Operation)
Input: !T
Output: F
Test Case 6 (Combined Operators)
Input: !(T && F)
Output: T
Test Case 7 (Parentheses Handling)
Input: T && (F || T)
Output: T
Test Case 8 (Complex Expression)
Input: !(T || F) && (T && !F)
Output: F
Q4.) Use YACC/Bison to generate 3-Address code for a given expression.
Flex Code→
%{
#include <string.h>
#include "tac.tab.h"
%}
%%
[0-9]+ { yylval.str = strdup(yytext); return NUMBER; }
[\t ]+ { /* Ignore spaces */ }
\n { }
"+" { return '+'; }
"-" { return '-'; }
"*" { return '*'; }
"/" { return '/'; }
"(" { return '('; }
")" { return ')'; }
. { printf("Invalid character: %s\n", yytext); }
%%
int yywrap() {
return 1;
}
Bison Code→
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void yyerror(const char *);
int yylex();
int tempVarCount = 1; //count no. of temp var
char* newTemp() {
char *temp = (char*)malloc(10);
sprintf(temp, "T%d", tempVarCount++);
return temp; // Return dynamically allocated memory
}
%}
%union {
char *str;
}
%token <str> NUMBER
%left '+' '-'
%left '*' '/'
%right UMINUS /* Unary minus has the highest precedence */
%type <str> expr
%%
input:
expr {
printf("\nThree Address Code Generated\n");
free($1);
}
;
expr:
expr '+' expr {
char *temp = newTemp();
printf("%s = %s + %s\n", temp, $1, $3);
$$ = temp;
free($1); free($3);
}
| expr '-' expr {
char *temp = newTemp();
printf("%s = %s - %s\n", temp, $1, $3);
$$ = temp;
free($1); free($3);
}
| expr '*' expr {
char *temp = newTemp();
printf("%s = %s * %s\n", temp, $1, $3);
$$ = temp;
free($1); free($3);
}
| expr '/' expr {
char *temp = newTemp();
printf("%s = %s / %s\n", temp, $1, $3);
$$ = temp;
free($1); free($3);
}
| '-' expr %prec UMINUS {
char *temp = newTemp();
printf("%s = -%s\n", temp, $2);
$$ = temp;
free($2);
}
| '(' expr ')' { $$ = $2; }
| NUMBER { $$ = $1; }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
printf("Enter an arithmetic expression:\n");
yyparse();
return 0;
}
# Test Cases→
Input→-5 + 3 * 4
Output→T1 = -5
T2 = 3 * 4
T3 = T1 + T2
Input→2*3-4
Output—>T1 = 2 * 3
T2 = T1 - 4
Input→((2*3-4))+5
Output→T1 = 2 * 3
T2 = T1 - 4
T3 = T2 + 5
Q5.) Use YACC/Bison to generate Syntax tree for a given expression
Flex Code→
%{
#include "st.tab.h"
#include<string.h>
#include <stdlib.h>
%}
%%
[0-9]+ { yylval.str = strdup(yytext); return NUMBER; }
[\t ]+ { /* Ignore whitespace */ }
"(" { return '('; }
")" { return ')'; }
"+" { return '+'; }
"-" { return '-'; }
"*" { return '*'; }
"/" { return '/'; }
\n { }
. { printf("Invalid character: %s\n", yytext); exit(1); }
%%
int yywrap(){
return 1;
}
Bison Code→
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
char *token;
struct Node *left, *right;
} Node;
Node* createNode(char *token1, Node *left, Node *right);
void printSyntaxTree(Node *root, int level);
void yyerror(const char *s);
int yylex();
%}
%union {
char *str;
struct Node *node;
}
%token <str> NUMBER
%left '+' '-'
%left '*' '/'
%right UMINUS /* Unary minus has highest precedence */
%type <node> expr
%%
input:
expr {
printf("\nSyntax Tree:\n");
printSyntaxTree($1, 0);
}
;
expr:
expr '+' expr {
$$ = createNode("+", $1, $3);
}
| expr '-' expr {
$$ = createNode("-", $1, $3);
}
| expr '*' expr {
$$ = createNode("*", $1, $3);
}
| expr '/' expr {
$$ = createNode("/", $1, $3);
}
| '-' expr %prec UMINUS {
$$ = createNode("UMINUS", $2, NULL);
}
| '(' expr ')' { $$ = $2; }
| NUMBER { $$ = createNode($1, NULL, NULL); }
;
%%
Node* createNode(char *token1, Node *left, Node *right) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->token = strdup(token1);
newNode->left = left;
newNode->right = right;
return newNode;
}
void printSyntaxTree(Node *root, int level) {
if (!root) return;
printSyntaxTree(root->right, level + 1);
for (int i = 0; i < level; i++) {
printf("\t"); // Indentation for tree structure
}
printf("%s\n", root->token);
printSyntaxTree(root->left, level + 1);
}
void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}
int main() {
printf("Enter an arithmetic expression:\n");
yyparse();
return 0;
}
Test Case 1:
Input→-5 + 2
Syntax Tree:
2
+
UMINUS
5
Interpretation→
+
/ \
UMINUS 2
|
5
Test Case 2:
Input→(8 - 3) * 4
Syntax Tree:
4
*
3
-
8
Interpretation→
*
/\
- 4
/\
8 3
Test Case 3:
Input→-((7 + 2) * 3) + 6 / (2 + 1)
Syntax Tree:
1
+
2
/
6
+
UMINUS
3
*
2
+
7
Interpretation→
+
/\
- /
/ /\
* + 6
/\ /\
+32 1
/\
7 2
*************************************************************************************************************