Skip to content
This repository was archived by the owner on Oct 16, 2022. It is now read-only.

Ankitz007/IntermediateCodeGeneration

Repository files navigation

Intermediate Code Generation

Intermediate Code Generation phase is the glue between the frontend and backend of the compiler design stages. The final goal of a compiler is to get programs written in a high-level language to run on a computer. This means that, eventually, the program will have to be expressed as machine code which can run on the computer. Many compilers use a medium-level language as a stepping-stone between the high-level language and the very low-level machine code. Such stepping-stone languages are called intermediate code. It provides lower abstraction from source level and maintains some high level information.

Intermediate Code can be represented in many different formats depending whether it is language-specific (e.g. Bytecode for Java) or language-independent (three-address-code). We have used three-address-code to make it independent. Most common independent intermediate representations are:

  • Postfix notation
  • Three Address Code
  • Syntax tree

Intermediate Code generation is the 4th phase in the design of a compiler. Before it, a compiler comprises of three other phases:

  • Lexical Analysis
  • Parsing
  • Semantic Analysis

Three Address Code

Three address code is a type of intermediate code which is easy to generate and can be easily converted to machine code.It makes use of at most three addresses and one operator to represent an expression and the value computed at each instruction is stored in a temporary variable generated by the compiler. The compiler decides the order of operation given by three address codes. General representation: x = y op z An address can be a name, constant or temporary.

  • Assignments x = y op z; x = op y.
  • Copy x = y.
  • Unconditional jump goto L.
  • Conditional jumps if x relop y goto L.
  • Parameters param x.
  • Function call y = call p

Hardware Requirements

Usage of CPU, RAM, and storage space can vary significantly based on user behavior. These hardware recommendations are based on my work on the project.

  • A Computer System
  • Ethernet connection (LAN) OR a wireless adapter (Wi-Fi)
  • Processor: Minimum 1 GHz
  • Sufficient memory to install required libraries

Software Requirements

Software requirements for the project are as follows:

  • GCC Compiler (for execution of C/C++ scripts)
  • Flex Compiler (for execution of lex scripts)
  • Bison Compiler (for execution of yacc scripts)
  • Bash Shell (To run bash scripts)

File Structure

.
├── Intermediate Code Generation
│   ├── parser.y
│   ├── run.sh
│   ├── scanner.l
│   ├── tests
├── Lexical Analysis
│   ├── Lexical Analysis.pdf
│   ├── run.sh
│   ├── scanner.l
│   └── tests
├── Parsing
│   ├── parser.y
│   ├── Parsing.pdf
│   ├── run.sh
│   ├── scanner.l
│   ├── tests
├── README.md
└── Semantic Analysis
     ├── parser.y
     ├── run.sh
     ├── scanner.l
     ├── Semantic Analysis.pdf
     ├── tests

8 directories, 47 files

Clearly, from the above structure, it can be seen that each phase is contained in an individual directory. So, if need be, one can see the working of each individual phase by going in the respective directory. Each directory will contain the following:

  • A bash script named run.sh.
  • A directory names tests with suitable test cases.
  • Lex or/and Yacc code as required.
  • Report regarding the working of the phase.

Execution Steps

To execute intermediate code generation, run the bash script placed in the directory. The bash script looks like this:

#!/bin/bash

YELLOW='\033[1;33m'
NOCOLOR='\033[0m'

function run() {
	flex scanner.l && yacc -d parser.y && gcc y.tab.c lex.yy.c -w
	local total_testcases="$1"
	echo "Running: $total_testcases"
	local start=1
	while [ $start -le $total_testcases ]
	do
		printf "\n\n"
		for i in {1..35}
		do
			echo -ne "="
		done
		echo -ne "  ${YELLOW}Running TestCase $start${NOCOLOR}  "
		for i in {1..35}
		do
			echo -ne "="
		done
		printf "\n"
		local filename="tests/test"$start".c"
		./a.out $filename
		((start++))
	done
}

number_of_files=`ls -l ./tests/ | egrep -c '^-'`
run $number_of_files

The workflow is explained as under:

  • Compile the script using Yacc tool

    $ yacc -d c_parser.y
  • Compile the flex script using Flex tool

    $ flex c_lexer.l
  • After compiling the lex file, a lex.yy.c file is generated. Also, y.tab.c and y.tab.h files are generated after compiling the yacc script.

  • The two files, lex.yy.c and y.tab.c are compiled together

      $ gcc -o compiler lex.yy.c y.tab.h y.tab.c -ll	

Usage Examples

Below are the screenshots of the execution of code.

ScreenShot 1

ScreenShot 2

ScreenShot 3

Developer Information

Name: Ankit Kumar Singh
USN: 1RV18IS007
Institute: R. V. College of Engineering
Instructor: Prof B. K. Srinivas

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published