0% found this document useful (0 votes)
11 views33 pages

Principle of Compiler Construction: Cbcpc14 Practical File

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

Principle of Compiler Construction: Cbcpc14 Practical File

Pcc
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 33

Principle of Compiler Construction

CBCPC14
PRACTICAL FILE
2024-25

Submitted by: Submitted to:

Name: Keshav Dr. R S Raw

Roll No.: 2022UCB6526

Branch: CSDA

Section: 1

Netaji Subhas University of Technology


(East Campus)
Geeta Colony, New Delhi
Delhi - 110031
INDEX

S. No. Experiments Page no. Sign

Develop simple language processors like desk calculator


1.
and assembler.

2. Design a small high-level language.

Develop a lexical analyzer and a syntax analyzer for a


3. simple high-level language using the LEX and YACC tools.
Also implement the bookkeeper module.

Design a small high-level language and implement a


compiler for the same. If the target machine of the
4.
compiler is a hypothetical machine, then implement a
simulator for it.

5. Develop a simple calculator using LEX and YACC tools.

6. Implement a program for symbol table using hashing

7. Implement a two-pass assembler

8. Implement a bottom-up parser using YACC tool.

9. Represent ‘C’ language using Context Free Grammar

Write a program to generate the three address code for


10.
the given expression.
Practical-1
Aim: Develop simple language processors like desk calculator and assembler.
1) Desk Calculator
Code:
#include <stdio.h>
#include <stdlib.h>
float calculate(float num1, float num2, char operator) {
switch (operator) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
if (num2 != 0) {
return num1 / num2;
} else {
printf("Error: Division by zero.\n");
exit(1);
}
default:
printf("Error: Invalid operator.\n");
exit(1);
}
}
int main() {
float num1, num2;
char operator;
printf("Enter first number: ");
scanf("%f", &num1);
printf("Enter an operator (+, -, *, /): ");
scanf(" %c", &operator);
printf("Enter second number: ");
scanf("%f", &num2);
float result = calculate(num1, num2, operator);
printf("Result: %.2f\n", result);
return 0;
}
Output:
2) Assembler
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void printMeaningfulInstruction(const char *instruction) {
char command[10];
char operand1[10];
char operand2[10];
int scanned = sscanf(instruction, "%s %s %s", command, operand1,
operand2);
if (scanned < 2) {
printf("Error: Invalid instruction format: %s\n", instruction);
return;
}
if (strcmp(command, "LOAD") == 0) {
printf("Meaning: Load value from %s into the accumulator.\n",
operand1);
} else if (strcmp(command, "STORE") == 0) {
printf("Meaning: Store value from the accumulator into %s.\n",
operand1);
} else if (strcmp(command, "ADD") == 0) {
if (scanned == 2) {
printf("Meaning: Add value from %s to the accumulator.\n",
operand1);
} else {
printf("Error: ADD requires one operand.\n");
}
} else if (strcmp(command, "SUB") == 0) {
if (scanned == 2) {
printf("Meaning: Subtract value from %s from the accumulator.\
n", operand1);
} else {
printf("Error: SUB requires one operand.\n");
}
} else if (strcmp(command, "MULT") == 0) {
if (scanned == 2) {
printf("Meaning: Multiply value from %s with the accumulator.\
n", operand1);
} else {
printf("Error: MULT requires one operand.\n");
}
} else if (strcmp(command, "DIV") == 0) {
if (scanned == 2) {
printf("Meaning: Divide the accumulator by value from %s.\n",
operand1);
} else {
printf("Error: DIV requires one operand.\n");
}
} else {
printf("Error: Unknown command %s\n", command);
}
}

int main() {
// Predefined assembly instructions
const char *instructions[] = {
"LOAD A",
"STORE B",
"ADD C",
"SUB D",
"MULT E",
"DIV F",
"ADD", // Example of missing operand
"LOAD A B", // Example of incorrect format (too many operands)
"UNKNOWN X" // Example of an unrecognized command
};

// Process each instruction


for (int i = 0; i < sizeof(instructions) / sizeof(instructions[0]); i++)
{
printf("Instruction: %s\n", instructions[i]);
printMeaningfulInstruction(instructions[i]);
printf("\n");
}
return 0;
}

Output:
Practical-2
Aim: Design a small high-level language.
Code:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
TOKEN_EOF,
TOKEN_VAR,
TOKEN_ID,
TOKEN_EQUALS,
TOKEN_NUMBER,
TOKEN_PLUS,
TOKEN_SEMICOLON
} TokenType;

// Define a token.
typedef struct {
TokenType type;
const char *start;
int length;
} Token;

// Declare the functions.


void lexer(const char *, Token *, int *);

int main() {
char input[1024];
printf("Enter code: ");
// Use fgets to read a full line with spaces.
if (!fgets(input, sizeof(input), stdin)) {
fprintf(stderr, "Error reading input.\n");
return 1;
}

const char *source = input;


Token tokens[256];
int tokenCount = 0;
lexer(source, tokens, &tokenCount);

// Print the tokens.


for (int i = 0; i < tokenCount; i++) {
printf("Token %d: type = %d, start = %.*s, length = %d\n",
i, tokens[i].type, tokens[i].length, tokens[i].start,
tokens[i].length);
}
return 0;
}

// Lexer function to tokenize the input.


void lexer(const char *source, Token *tokens, int *tokenCount) {
const char *start = source;
while (*source != '\0') {
if (isspace(*source)) {
// Ignore all the whitespace.
source++;
start = source;
} else if (isalpha(*source)) {
// Identifier or keyword.
while (isalpha(*source)) {
source++;
}
if (source - start == 3 && strncmp(start, "var", 3) == 0) {
tokens[*tokenCount].type = TOKEN_VAR;
} else {
tokens[*tokenCount].type = TOKEN_ID;
}
tokens[*tokenCount].start = start;
tokens[*tokenCount].length = source - start;
(*tokenCount)++;
start = source;
} else if (isdigit(*source)) {
// Number
while (isdigit(*source)) {
source++;
}
tokens[*tokenCount].type = TOKEN_NUMBER;
tokens[*tokenCount].start = start;
tokens[*tokenCount].length = source - start;
(*tokenCount)++;
start = source;
} else {
// Operator or punctuation.
switch (*source) {
case '=':
tokens[*tokenCount].type = TOKEN_EQUALS;
break;
case '+':
tokens[*tokenCount].type = TOKEN_PLUS;
break;
case ';':
tokens[*tokenCount].type = TOKEN_SEMICOLON;
break;
default:
printf("Unknown character: %c\n", *source);
return;
}
tokens[*tokenCount].start = start;
tokens[*tokenCount].length = 1;
(*tokenCount)++;
source++;
start = source;
}
}
// Add the EOF token at the end.
tokens[*tokenCount].type = TOKEN_EOF;
tokens[*tokenCount].start = start;
tokens[*tokenCount].length = 0;
(*tokenCount)++;
}

Output:
Practical-3
Aim: Develop a lexical analyzer and a syntax analyzer for a simple high-level language using the
LEX and YACC tools. Also implement the bookkeeper module.

Code:
1) Create and Compile Lex file (lex simple.l)
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h" // This header file is generated by YACC
%}

%%

[0-9]+ { yylval.num = atoi(yytext); return NUMBER; }


"=" { return ASSIGN; }
"+" { return ADD; }
"-" { return SUB; }
"*" { return MUL; }
"/" { return DIV; }
"(" { return LPAREN; }
")" { return RPAREN; }
[ \t\n] { /* skip whitespace */ }
[A-Za-z_][A-Za-z0-9_]* { yylval.str = strdup(yytext); return
IDENTIFIER; }

%%

int yywrap(void) {
return 1;
}

2) Create and Compiler Yacc file (yacc -d simple.y)


%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bookkeeper.h" // Include the bookkeeper module
%}

%union {
int num;
char* str;
}

%token <num> NUMBER


%token <str> IDENTIFIER
%token ASSIGN ADD SUB MUL DIV LPAREN RPAREN

%type <num> expression term factor

%%

program:
program statement
| /* empty */
;

statement:
IDENTIFIER ASSIGN expression {
add_variable($1, $3); // Add the variable to bookkeeper
printf("Assigned %d to %s\n", $3, $1);
}
| expression {
printf("Result: %d\n", $1);
}
;

expression:
term {
$$ = $1;
}
| expression ADD term {
$$ = $1 + $3;
}
| expression SUB term {
$$ = $1 - $3;
}
;

term:
factor {
$$ = $1;
}
| term MUL factor {
$$ = $1 * $3;
}
| term DIV factor {
$$ = $1 / $3;
}
;

factor:
NUMBER {
$$ = $1;
}
| IDENTIFIER {
$$ = get_variable($1); // Get the value from bookkeeper
}
| LPAREN expression RPAREN {
$$ = $2;
}
;

%%

int main(void) {
yyparse();
return 0;
}

int yyerror(char *s) {


fprintf(stderr, "Syntax error: %s\n", s);
return 0;
}

3) Create c file for bookkeeper module


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_VARS 100

typedef struct {
char* name;
int value;
} Variable;

Variable variables[MAX_VARS];
int var_count = 0;

int get_variable(char* name) {


for (int i = 0; i < var_count; i++) {
if (strcmp(variables[i].name, name) == 0) {
return variables[i].value;
}
}
printf("Error: Undefined variable %s\n", name);
exit(1); // Exit if the variable is not found
}

void add_variable(char* name, int value) {


// Check if the variable already exists
for (int i = 0; i < var_count; i++) {
if (strcmp(variables[i].name, name) == 0) {
variables[i].value = value;
return;
}
}

// Add a new variable


if (var_count < MAX_VARS) {
variables[var_count].name = strdup(name);
variables[var_count].value = value;
var_count++;
} else {
printf("Error: Maximum variable limit reached\n");
exit(1);
}
}

4) Create header file for bookkeeper module (bookkeeper.h)


#ifndef BOOKKEEPER_H
#define BOOKKEEPER_H
int get_variable(char* name);
void add_variable(char* name, int value);

#endif

5) Compile Yacc Output (gcc -c y.tab.c)


6) Compile lex Output (gcc -c lex.yy.c)
7) Run (gcc lex.yy.o y.tab.o bookkeeper.c -o simple) to link everything and create execution
file
8) Run ./simple <input.txt in terminal

Input:

Output:

Practical-4
Aim: Design a small high-level language and implement a compiler for the same. If the target
machine of the compiler is a hypothetical machine, then implement a simulator for it.

Code:

1) Create and Compile Lex file (lex MiniLang.l)

%{
#include "MiniLang.tab.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
%}
%%
let { return LET; }
if { return IF; }
then { return THEN; }
else { return ELSE; }
print { return PRINT; }

\"[^\"]*\" { yylval.sval = strdup(yytext); return STRING; } // Match


strings
[0-9]+ { yylval.ival = atoi(yytext); return NUMBER; }
[a-zA-Z_][a-zA-Z0-9_]* { yylval.sval = strdup(yytext); return IDENTIFIER;
}

"=" { return ASSIGN; }


";" { return SEMICOLON; }
"+" { return PLUS; }
"*" { return MULT; }
">" { return GT; }

[ \t\n] { /* Ignore whitespace */ }


. { printf("Unknown character: %s\n", yytext); }

%%

int yywrap() {
return 1;
}

2) Create and Compiler Yacc file (yacc -d MiniLang.y)


%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Define a symbol table for variable storage


typedef struct {
char *name;
int value;
} Symbol;

Symbol symbolTable[100];
int symbolCount = 0;

// Function to add or update a symbol in the symbol table


void setSymbolValue(char *name, int value) {
for (int i = 0; i < symbolCount; i++) {
if (strcmp(symbolTable[i].name, name) == 0) {
symbolTable[i].value = value;
return;
}
}
symbolTable[symbolCount].name = strdup(name);
symbolTable[symbolCount].value = value;
symbolCount++;
}

// Function to retrieve a symbol's value


int getSymbolValue(char *name) {
for (int i = 0; i < symbolCount; i++) {
if (strcmp(symbolTable[i].name, name) == 0) {
return symbolTable[i].value;
}
}
printf("Error: Undefined variable %s\n", name);
return 0;
}

// Error handler function


void yyerror(const char *s) {
fprintf(stderr, "Error: %s\n", s);
}

%}

// Define the types of values yylval can hold


%union {
int ival; // For integer values
char *sval; // For identifiers and strings
}

// Token declarations with data types


%token <ival> NUMBER
%token <sval> IDENTIFIER STRING
%token LET IF THEN ELSE PRINT ASSIGN SEMICOLON PLUS MULT GT

// Non-terminal declarations with data types


%type <ival> expression term factor condition

%%
// Define the grammar rules

program:
statements
;

statements:
statement SEMICOLON statements
| statement SEMICOLON
;

statement:
LET IDENTIFIER ASSIGN expression { setSymbolValue($2, $4);
printf("Assign %s = %d\n", $2, $4); }
| IF condition THEN statement ELSE statement { printf("Conditional
statement\n"); }
| PRINT expression { printf("Print %d\n",
$2); }
| PRINT STRING { printf("Print %s\n",
$2); }
;

condition:
expression GT expression { $$ = ($1 > $3); }
;

expression:
expression PLUS term { $$ = $1 + $3; }
| term { $$ = $1; }
;

term:
term MULT factor { $$ = $1 * $3; }
| factor { $$ = $1; }
;

factor:
NUMBER { $$ = $1; }
| IDENTIFIER { $$ =
getSymbolValue($1); }
;

%%

// Main function to initiate parsing


int main() {
return yyparse();
}
3) Run (gcc lex.yy.c y.tab.c -o MiniLangCompiler) to create execution file

4) Run ./MiniLangCompiler <input.txt in terminal

Input:

Output:

Practical-5
Aim: Develop a simple calculator using LEX and YACC tools.
Code:
1) Create and Compile Lex file (lex calc.l)

%{
#include<stdlib.h>
#include "y.tab.h"
extern int yylval;
%}
%%

[0-9]+ {yylval=atoi(yytext); return NUMBER;}

">=" return GE;


"<=" return LE;
"!=" return NE;
"==" return EQ;
[\n] return 0;
[\t];

. return yytext[0];
%%

2) Create and Compiler Yacc file (yacc -d calc.y)

%{
#include<stdio.h>
%}

%token NAME NUMBER


%left GE LE NE EQ '<' '>' '%'
%left '-' '+'
%left '*' '/'
%nonassoc UMINUS
%%

statement : NAME '=' exp


|exp {printf("=%d\n",$1);}
;

exp : NUMBER {$$ == $1;}


|exp '+' exp {$$ = $1 + $3 ;}
|exp '-' exp {$$ = $1 - $3 ;}
|exp '*' exp {$$ = $1 * $3 ;}
|exp '/' exp {$$ = $1 / $3 ;}
|exp '<' exp {$$ = $1 < $3 ;}
|exp '>' exp {$$ = $1 > $3 ;}
|exp '%' exp {$$ = $1 % $3 ;}
|exp GE exp {$$ = $1 >= $3 ;}
|exp LE exp {$$ = $1 <= $3 ;}
|exp EQ exp {$$ = $1 == $3 ;}
|exp NE exp {$$ = $1 != $3 ;}
|exp '-' exp %prec UMINUS {$$ = -$2 ;}
|'(' exp ')' {$$ = $2 ;}
;
%%
int main(){
yyparse();
}

int yyerror(){}

int yywrap(){
return 1;
}

3) Run (gcc lex.yy.c y.tab.c) to create execution file

4) Run ./a.out in terminal

Output:

Practical-6
Aim: Implement a program for symbol table using hashing.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Define the maximum number of slots in the hash table


#define TABLE_SIZE 10
// Define the symbol table entry structure
typedef struct Entry {
char key[100]; // symbol name
int value; // associated value
struct Entry* next; // pointer to the next entry in case of a collision
} Entry;

// Define the hash table structure


typedef struct {
Entry* table[TABLE_SIZE]; // an array of pointers to entry lists
} SymbolTable;

// Hash function to convert key into an index


unsigned int hash(char* key) {
unsigned int hashValue = 0;
while (*key) {
hashValue = (hashValue << 5) + *key; // simple hash function
key++;
}
return hashValue % TABLE_SIZE;
}

// Initialize a symbol table


void initSymbolTable(SymbolTable* symbolTable) {
for (int i = 0; i < TABLE_SIZE; i++) {
symbolTable->table[i] = NULL;
}
}

// Insert a new symbol into the table


void insert(SymbolTable* symbolTable, char* key, int value) {
unsigned int index = hash(key);
Entry* newEntry = (Entry*)malloc(sizeof(Entry));
strcpy(newEntry->key, key);
newEntry->value = value;
newEntry->next = symbolTable->table[index]; // link new entry to the
existing list
symbolTable->table[index] = newEntry;
}

// Search for a symbol by its key


int search(SymbolTable* symbolTable, char* key) {
unsigned int index = hash(key);
Entry* entry = symbolTable->table[index];
while (entry != NULL) {
if (strcmp(entry->key, key) == 0) {
return entry->value; // symbol found, return its value
}
entry = entry->next;
}
return -1; // symbol not found
}

// Delete a symbol from the table


void delete(SymbolTable* symbolTable, char* key) {
unsigned int index = hash(key);
Entry* entry = symbolTable->table[index];
Entry* prev = NULL;

// Traverse the linked list at the index


while (entry != NULL && strcmp(entry->key, key) != 0) {
prev = entry;
entry = entry->next;
}

// If the symbol is found


if (entry != NULL) {
if (prev == NULL) {
symbolTable->table[index] = entry->next;
} else {
prev->next = entry->next;
}
free(entry); // free the memory
}
}

// Display the symbol table with a clearer format


void display(SymbolTable* symbolTable) {
printf("\n----- Symbol Table -----\n");
for (int i = 0; i < TABLE_SIZE; i++) {
Entry* entry = symbolTable->table[i];
if (entry != NULL) {
printf("Index %d: ", i);
while (entry != NULL) {
printf("(%s, %d)", entry->key, entry->value);
entry = entry->next;
if (entry != NULL) printf(" -> ");
}
printf("\n");
}
}
printf("------------------------\n");
}

int main() {
SymbolTable symbolTable;
initSymbolTable(&symbolTable);
int choice, value;
char key[100];

do {
printf("\n------ Menu ------\n");
printf("1. Insert Symbol\n");
printf("2. Search Symbol\n");
printf("3. Delete Symbol\n");
printf("4. Display Symbol Table\n");
printf("5. Exit\n");
printf("Enter your choice: ");
scanf("%d", &choice);

switch(choice) {
case 1:
printf("Enter symbol name: ");
scanf("%s", key);
printf("Enter symbol value: ");
scanf("%d", &value);
insert(&symbolTable, key, value);
printf("Symbol inserted.\n");
break;

case 2:
printf("Enter symbol name to search: ");
scanf("%s", key);
value = search(&symbolTable, key);
if (value == -1)
printf("Symbol not found.\n");
else
printf("Symbol '%s' found with value: %d\n", key,
value);
break;

case 3:
printf("Enter symbol name to delete: ");
scanf("%s", key);
delete(&symbolTable, key);
printf("Symbol deleted (if it existed).\n");
break;

case 4:
display(&symbolTable);
break;

case 5:
printf("Exiting the program.\n");
break;

default:
printf("Invalid choice! Please try again.\n");
}
} while(choice != 5);

return 0;
}

Output:
Practical-7
Aim: Implement a two-pass assembler.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LABELS 100


#define MAX_CODE_LINES 100
#define MAX_LINE_LENGTH 100

typedef struct {
char label[MAX_LINE_LENGTH];
int address;
} Symbol;

Symbol symbolTable[MAX_LABELS];
int symbolCount = 0;
int currentAddress = 0;

char code[MAX_CODE_LINES][MAX_LINE_LENGTH];
int codeLineCount = 0;

void addSymbol(const char* label, int address) {


strcpy(symbolTable[symbolCount].label, label);
symbolTable[symbolCount].address = address;
symbolCount++;
}

int findSymbol(const char* label) {


for (int i = 0; i < symbolCount; i++) {
if (strcmp(symbolTable[i].label, label) == 0) {
return symbolTable[i].address;
}
}
return -1;
}

void firstPass(FILE *input) {


char line[MAX_LINE_LENGTH];
while (fgets(line, sizeof(line), input)) {
char label[MAX_LINE_LENGTH], instruction[MAX_LINE_LENGTH];

strcpy(code[codeLineCount++], line);

if (sscanf(line, "%s %s", label, instruction) == 2) {


if (label[strlen(label) - 1] == ':') {
label[strlen(label) - 1] = '\0';
addSymbol(label, currentAddress);
}
}
currentAddress++;
}

printf("Symbol Table:\n");
for (int i = 0; i < symbolCount; i++) {
printf("Label: %s, Address: %d\n", symbolTable[i].label,
symbolTable[i].address);
}
}

void secondPass() {
for (int i = 0; i < codeLineCount; i++) {
char label[MAX_LINE_LENGTH], instruction[MAX_LINE_LENGTH],
operand[MAX_LINE_LENGTH];

if (sscanf(code[i], "%s %s %s", label, instruction, operand) == 3) {


if (label[strlen(label) - 1] == ':') {
strcpy(instruction, operand);
sscanf(code[i], "%*s %s %s", instruction, operand);
}
} else if (sscanf(code[i], "%s %s", instruction, operand) == 2) {
if (strcmp(instruction, "JMP") == 0) {
int address = findSymbol(operand);
if (address != -1) {
printf("JMP %d\n", address);
} else {
printf("Undefined label %s\n", operand);
}
} else {
printf("%s %s\n", instruction, operand);
}
} else if (sscanf(code[i], "%s", instruction) == 1) {
printf("%s\n", instruction);
}
}
}

int main() {
FILE *input = fopen("assembly.txt", "r");
if (!input) {
perror("File opening failed");
return EXIT_FAILURE;
}

firstPass(input);
rewind(input);

secondPass();
fclose(input);
return 0;
}

Input:

Output:
Practical-8
Aim: Implement a bottom-up parser using YACC tool.
Code:
1) Create and Compile Lex file (lex lexer.l)

%{
#include <stdio.h>
#include "y.tab.h" // Include the header generated by YACC for token
definitions
%}

%%
[0-9]+ { yylval.dval = atof(yytext); return DIGIT; } // Recognize numbers
and convert to double
\n|. { return yytext[0]; } // Pass newline or any other character
%%

2) Create and Compiler Yacc file (yacc -d parser.y)

%{
#include <stdio.h>
%}

%union {
double dval; // Use a double to store numeric values
}

%token <dval> DIGIT // Define DIGIT as a token with a double value


%type <dval> expr term factor // Declare types for grammar symbols

%%
line: expr '\n' { printf("%g\n", $1); } // Print result of expression on
a new line
;

expr: expr '+' term { $$ = $1 + $3; } // Define addition


| term
;

term: term '*' factor { $$ = $1 * $3; } // Define multiplication


| factor
;

factor: '(' expr ')' { $$ = $2; } // Handle expressions within


parentheses
| DIGIT
;
%%

// Main and error-handling functions


int main() {
return yyparse();
}

void yyerror(char *s) {


printf("%s\n", s);
}

3) Run (gcc lex.yy.c y.tab.c) to create execution file

4) Run ./a.out in terminal

Output:
Practical-9
Aim: Represent ‘C’ language using Context Free Grammar.
Representation:
Practical-10
Aim: Write a code to generate the three address code for the given expression.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct three {
char data[10], temp[7];
} s[30];

void main() {
char d1[7], d2[7] = "t";
int i = 0, j = 1, len = 0;
FILE *f1;

// Open the file and check for errors


f1 = fopen("sum.txt", "r");
if (f1 == NULL) {
printf("Error opening sum.txt\n");
return;
}

// Read the input expression into the struct


while (fscanf(f1, "%s", s[len].data) != EOF) {
len++;
}

// Start processing the first operation


sprintf(d1, "%d", j); // Use sprintf for integer to string conversion
strcat(d2, d1);
strcpy(s[j].temp, d2);
strcpy(d1, "");
strcpy(d2, "t");

// Handle the first operator (+, -, *, /)


if (strcmp(s[3].data, "+") == 0) {
printf("%s=%s+%s\n", s[j].temp, s[i + 2].data, s[i + 4].data);
j++;
} else if (strcmp(s[3].data, "-") == 0) {
printf("%s=%s-%s\n", s[j].temp, s[i + 2].data, s[i + 4].data);
j++;
} else if (strcmp(s[3].data, "*") == 0) {
printf("%s=%s*%s\n", s[j].temp, s[i + 2].data, s[i + 4].data);
j++;
} else if (strcmp(s[3].data, "/") == 0) {
printf("%s=%s/%s\n", s[j].temp, s[i + 2].data, s[i + 4].data);
j++;
}

// Handle subsequent operations


for (i = 4; i < len - 2; i += 2) {
sprintf(d1, "%d", j);
strcat(d2, d1);
strcpy(s[j].temp, d2);

if (strcmp(s[i + 1].data, "+") == 0) {


printf("%s=%s+%s\n", s[j].temp, s[j - 1].temp, s[i + 2].data);
} else if (strcmp(s[i + 1].data, "-") == 0) {
printf("%s=%s-%s\n", s[j].temp, s[j - 1].temp, s[i + 2].data);
} else if (strcmp(s[i + 1].data, "*") == 0) {
printf("%s=%s*%s\n", s[j].temp, s[j - 1].temp, s[i + 2].data);
} else if (strcmp(s[i + 1].data, "/") == 0) {
printf("%s=%s/%s\n", s[j].temp, s[j - 1].temp, s[i + 2].data);
}

strcpy(d1, "");
strcpy(d2, "t");
j++;
}

// Print the final result


printf("%s=%s\n", s[0].data, s[j - 1].temp);

// Close the file


fclose(f1);
}

Input:

Output:

You might also like