0% found this document useful (0 votes)
18 views14 pages

Practice Assignment 2

The document contains exercises for using YACC/Bison to create programs for converting binary to decimal, evaluating arithmetic expressions, and generating three-address code and syntax trees. It includes detailed Flex and Bison code examples for each exercise, along with test cases to demonstrate functionality. The exercises cover a range of topics including binary conversion, arithmetic evaluation, Boolean expression evaluation, and syntax tree generation.

Uploaded by

Vansh Raj Singh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views14 pages

Practice Assignment 2

The document contains exercises for using YACC/Bison to create programs for converting binary to decimal, evaluating arithmetic expressions, and generating three-address code and syntax trees. It includes detailed Flex and Bison code examples for each exercise, along with test cases to demonstrate functionality. The exercises cover a range of topics including binary conversion, arithmetic evaluation, Boolean expression evaluation, and syntax tree generation.

Uploaded by

Vansh Raj Singh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

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

*************************************************************************************************************

You might also like