Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 10

BCSE307L -Compiler Design Lab

Winter Semester 2023-24

Prepared by:

Name : Sandhit Karmakar – 21BAI743

Slot: L15+L16
LAB -4

Submitted to: Dr. Sureshkumar WI


AIM:
Implementation of a simple calculator using LEX and YACC tools.

ALGORITHM:
1. Lexer (calculator.l):
- Include the required header files and declare the yylval variable.
- Define token patterns and their corresponding actions using regular expressions.
- Convert recognized numbers to integers and assign them to yylval.
- Return the appropriate tokens for operators and other characters. - Handle special characters like tabs
and newlines.
2. Parser (calculator.y):
- Include the necessary header files and define variables.
- Declare the tokens using the %token directive.
- Specify the operator precedence using %left directives.
- Define grammar rules for arithmetic expressions using BNF notation.
- Calculate the result and print it in the ArithmeticExpression rule.
- Handle different operators and parentheses by recursively evaluating expressions.
- Assign the value of numbers to $$ (the result).
3. Main Function:
- Prompt the user to enter an arithmetic expression.
- Invoke the parser using yyparse() to evaluate the expression.
- Print the result if the expression is valid.
- Display an error message if the expression is invalid.

4. Error Handling:
- Implement the yyerror() function to handle parsing errors.
- Set a flag variable to indicate an invalid expression.
- Terminate the program.

CODE :
// Calculator.l
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {
yylval = atoi(yytext);
return NUMBER;
}
[\t] ;
[\n] return 0;
. return yytext[0];
%%
int yywrap()
{
return 1;
}
// Calculator.y
%{
#include <stdio.h>
int flag = 0;
%}
%token NUMBER
%left '+' '-'
%left '*' '/' '%'
%left '(' ')'
%%
ArithmeticExpression:
E{
printf("\nResult = %d\n", $$);
return 0;
};
E:
E '+' E { $$ = $1 + $3; }
| E '-' E { $$ = $1 - $3; }
| E '*' E { $$ = $1 * $3; }
| E '/' E { $$ = $1 / $3; }
| E '%' E { $$ = $1 % $3; }
| '(' E ')' { $$ = $2; }

| NUMBER { $$ = $1; }
;
%%
int main(void)
{
printf("\nEnter Arithmetic Expression:\n");
yyparse();
if (flag == 0)
printf("\nEntered arithmetic expression is valid\n\n");
return 0;
}
void yyerror(const char *s)
{
printf("\nEntered arithmetic expression is invalid\n\n");
flag = 1;
}

Input :
The input for this program would be stored in a linear array. Here the input is :
For Addition the following input is given:
“4+5”
For Subtraction the following input is given:
“5-4”
For Multiplication the following input is given:
“4*5”
For Division the following input is given:
“5/4”

Constraint:
The Arithmetic Expression must have operations like Addition, Subtraction, Multiplication,
Division, Modulus and Round brackets only.

Output :
Conclusion :
By leveraging LEX for token recognition and YACC for grammar rules and evaluation, the code achieves
accurate parsing and evaluation of expressions involving basic operators.
AIM:
Implementation of Abstract syntax tree –Infix to postfix using the LEX and YACC tools.

Algorithm :
- Define the lexer rules in the `infix_to_postfix.l` file to tokenize the input expression into
identifiers
(IDs) and operators.
- Utilize the Lex tool to implement the lexer and generate the lexer code (`lex.yy.c`).
- Define the Yacc rules in the `infix_to_postfix.y` file to specify the grammar for the infix
expression
and postfix conversion.
- Use the Yacc tool to implement the parser and generate the parser code (`y.tab.c`).
- Define the necessary data structures, such as the node structure, to represent the expression
tree.
- Implement the functions `mkleaf` and `mknode` to create leaf nodes and operator nodes in
the
expression tree.
- Implement the `display` function to print the preorder traversal of the expression tree.
- Implement the `convertToPostfix` function to convert the infix expression to postfix notation
by
traversing the expression tree in postorder.
- Implement the `yyerror` function to handle parsing errors and display error messages.
- In the `main` function, call `yyparse` to initiate the parsing process.
- Inside the `stmt` rule, call `convertToPostfix` to convert the infix expression to postfix and
display
the result.
- Terminate the program.
These steps outline the process of creating a lexer and parser using Lex and Yacc to convert an
infix
expression to postfix notation, building an expression tree, and performing various operations
on it.

Code :
// Lex
%{
#include "y.tab.h"
extern int yylval;
void yyerror(char *error);
%}
L [a-zA-Z]
%%
{L} { yylval = (int)yytext[0]; return ID; }
. { return *yytext; }
[\t];
[\n] return 0;
%%
int yywrap() {
return 1;
}
// YACC
%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();
extern int yyparse();
typedef union {
int intval;
char charval;
} type;
typedef struct node {
type data;
struct node* lptr, * rptr;
} node;
node* mknode(char dt, node* ln, node* rn);
node* mkleaf(char dt, node* ln, node* rn);
void display(node* root);
void convertToPostfix(node* root);
int op;
%}
%union {
int intval;
char charval;
struct node* nptr;
}
%token <intval> NUM
%token <charval> ID
%type <nptr> exp
%type <nptr> postfix
%left '*' '/'
%left '+' '-'
%right '^'
%start stmt
%%
stmt: exp {
printf("\nPostfix Expression: ");
convertToPostfix($1);
printf("\n");
}
exp: ID {
$$ = mkleaf($1, NULL, NULL);
}
| exp '=' exp {
$$ = mknode('=', $1, $3);
}
| exp '+' exp {
$$ = mknode('+', $1, $3);
}
| exp '-' exp {
$$ = mknode('-', $1, $3);
}
| exp '*' exp {
$$ = mknode('*', $1, $3);
}
| exp '/' exp {
$$ = mknode('/', $1, $3);
}
postfix: exp {
$$ = $1;
}
%%
node* mkleaf(char dt, node* ln, node* rn) {
node* temp = (node*)malloc(sizeof(node));
temp->data.charval = dt;
temp->lptr = ln;
temp->rptr = rn;
return temp;
}
node* mknode(char dt, node* ln, node* rn) {
node* temp = (node*)malloc(sizeof(node));
temp->data.charval = dt;
temp->lptr = ln;
temp->rptr = rn;
return temp;
}
void display(node* root) {
if (root != NULL) {
if (root->lptr == NULL && root->rptr == NULL) {
printf("%c", root->data.charval);
}
else {
printf("%c", root->data.charval);
}
display(root->lptr);
display(root->rptr);
}
}
void convertToPostfix(node* root) {
if (root != NULL) {
convertToPostfix(root->lptr);
convertToPostfix(root->rptr);
printf("%c", root->data.charval);
}
}
void yyerror(char* error) {
printf("\n%s", error);
}
int main() {
yyparse();
return 0;
}

Input:
Here, the given input is a+b*c which is the infix expression

Output:
The program will covert infix expression to postfix

Conclusion:
In summary, the code effectively utilizes the LEX and YACC tools to build an Abstract Syntax Tree
(AST) for converting infix expressions to postfix notation. The lexer (infix_to_postfix.l) is responsible for
tokenizing the input expression, while the parser (infix_to_postfix.y) defines the grammar rules and
constructs the AST. The AST enables efficient conversion of infix expressions to postfix notation,
facilitating further processing or evaluation of the expressions

You might also like