Compiler Design is the structure and set of principles that guide the translation, analysis, and optimization process of a compiler.
A Compiler is computer software that transforms program source code which is written in a high-level language into low-level machine code. It essentially translates the code written in one programming language to another language without changing the logic of the code.
The Compiler also makes the code output efficient and optimized for execution time and memory space. The compiling process has basic translation mechanisms and error detection, it can’t compile code if there is an error. The compiler process runs through syntax, lexical, and semantic analysis in the front end and generates optimized code in the back end.
When executing, the compiler first analyzes all the language statements one after the other syntactically and then, if it’s successful, builds the output code, making sure that statements that refer to other statements are referred to appropriately, Traditionally, the output code is called Object Code.
Types of Compiler
- Cross Compiler: This enables the creation of code for a platform other than the one on which the compiler is running. For instance, it runs on a machine ‘A’ and produces code for another machine ‘B’.
- Source-to-source Compiler: This can be referred to as a transcompiler or transpiler and it is a compiler that translates source code written in one programming language into source code of another programming language.
- Single Pass Compiler: This directly transforms source code into machine code. For instance, Pascal programming language.
- Two-Pass Compiler: This goes through the code to be translated twice; on the first pass it checks the syntax of statements and constructs a table of symbols, while on the second pass it actually translates program statements into machine language.
- Multi-Pass Compiler: This is a type of compiler that processes the source code or abstract syntax tree of a program multiple times before translating it to machine language.
Language Processing Systems Steps
- High-Level Language: These are programs that contain
#includedirectives such as
#define. They are closer to humans language but far from machines. The (
#) tags are referred to as preprocessor directives. They tell the pre-processor about what to do.
- Pre-Processor: This produces input for the compiler and also deals with file inclusion, augmentation, macro-processing, language extension, etc. It removes all the
#includedirectives by including the files called file inclusion and all the
#definedirectives using macro expansion.
- Assembler: This translates assembly language code into machine understandable language. Each platform (OS + Hardware) has its own assembler. The output of an assembler is known as an object file which is a combination of machine instruction along with the data required to store these instructions in memory.
- Interpreter: An interpreter converts high-level language into low-level machine language almost similar to what Compiler does. The major difference between both is that the interpreter reads and transforms code line by line while Compiler reads the entire code at once and outputs the machine code directly. Another difference is, Interpreted programs are usually slower with respect to compiled ones.
- Relocatable Machine Code: This can be loaded at any point in time and can be run. This enables the movement of a program using its unique address identifier.
- Linker: It links and merges a variety of object files into a single file to make it executable. The linker searches for defined modules in a program and finds out the memory location where all modules are stored.
- Loader: It loads the output from the Linker in memory and executes it. It basically loads executable files into memory and runs them
Features Of A Compiler
Correctness: A major feature of a compiler is its correctness, and accuracy to compile the given code input into its exact logic in the output object code due to its being developed using rigorous testing techniques (often called compiler validation) on an existing compiler.
Recognize legal and illegal program constructs: Compilers are designed in such a way that they can identify which part of the program formed from one or more lexical tokens using the appropriate rules of the language is syntactically allowable and which is not.
Good Error reporting/handling: A compiler is designed to know how to parse the error encountered from lack be it a syntactical error, insufficient memory errors, or logic errors are meticulously handled and displayed to the user.
The Speed of the target code: Compilers make sure that the target code is fast because in huge size code its a serious limitation if the code is slow, some compilers do so by translating the bytecode into target code to run in the specific processor using classical compiling methods.
Preserve the correct meaning of the code: A compiler makes sure that the code logic is preserved to the tiniest detail because a single loss in the code logic can change the whole code logic and output the wrong result, so during the design process, the compiler goes through a whole lot of testing to make sure that no code logic is lost during the compiling process.
Code debugging help: Compilers make help the debugging process easier by pointing out the error line to the programmer and telling them the type of error that is encountered so they would know how to start fixing it.
Benefits Of Using A Compiler:
Improved performance: Using a compiler increases your program performance, by making the program optimized, portable, and easily run on the specific hardware.
Reduced system load: Compilers make your program run faster than interpreted programs because it compiles the program only once, hence reducing system load and response time when next you run the program.
Protection for source code and programs: Compilers protect your program source by discouraging other users from making unauthorized changes to your programs, you as the author can distribute your programs in object code.
Portability of compiled programs: Compiled programs are always portable meaning that you can transfer it from one machine to another without worrying about dependencies as it is all compiled together.