COMPILER
A compiler is a special type of computer program (or set of Instructions) that translates a human readable (source program) text file into a form that the computer can more easily understand. It has a nick name called translator. At its most basic level, a computer can only understand two things, a 1 and a 0. At this level, a human will operate very slowly and find the information contained in the long string of 1s and 0s incomprehensible, but compiler bridges this gap. The most common reason to translate source program is to create an executable program. The generated machine code can be executed many times against different data each time.
In the beginning, compilers were very simple programs that could only translate symbols into the bits, the 1s and 0s, the computer understood. Programs were also very simple, composed of a series of steps that were originally translated by hand into the data the computer could understand. When programs starts growing larger, translating through hand became bulky and also time consuming task, so portions of this task were automated or programmed, and the first compiler was written.
These simple compilers were used to write more sophisticated compiler. With the newer versions, more rules could be added to the compiler program to allow a more natural language structures for the human programmer to operate with. This made writing programs easier and allowed more people to begin writing programs. As more people started writing programs, more ideas about writing programs were offered and used to make more sophisticated compilers.
The compiler has another task apart from the translating your program. If any grammatical errors are found during compilation than it will display that what the error is. An error detected by the compiler is known as compile-time error or syntax error.
Basic Properties of Compiler
· A compiler must be error-free.
· A compiler must always stop, no matter what the input looks like.
· A compiler should attempt to find as many errors as possible during a single compilation process.
Advantages
1. One of the biggest advantages of Compiled languages is their execution speed. A program written in C/C++ runs more 30-70% faster than an equivalent program written in Java.
2. Compiled code also takes less memory as compared to an interpreted program.
Disadvantages
1. A compiler is much more difficult to write than an interpreter.
2. A compiler does not provide much help in debugging a program – how many times have you received a null pointer error in your C code and have spent hours trying to figure out where in your source code did the error occurred.
3. The executable Compiled code is much bigger in size than an equivalent interpreted code. For example, C/C++ .exe file is much bigger than an equivalent Java.class file.
4. Compiled programs are targeted towards a particular platform and hence are platform dependent.
5. Compiled programs do not allow security to be implemented within the code. For example, a compiled program can access any area of the memory, and can do whatever it wants with your PC (most of the viruses are made in compiled languages).
6. Due to loose security and platform dependence - a compiled language is not particularly suited to be used to develop Internet or web-based applications.
INTERPRETER
An interpreter translates programming language statements in a different way than a compiler. Rather than creating a compile object module for a program, an interpreter reads, translates and executes the source program one line at a time. It performs the translation into machine language while the program runs. Languages that are interpreted are:JavaScript, PHP, and Ruby.
Advantages
1. A program can be run immediately after being written.
2. Execution usually stops at the point where an error is encountered. They help programmers to find errors in programs easily.
3. It occupies less space than compiler because it does not generate object modules which take more space.
4. There is no lengthy compile time, i.e. you don’t have to wait between writing a program and running it, for it to compile. As soon as you have written a program, you can run it.
5. Interpreters are often used in education because they allow students to program interactively.
6. Entire program does not have to be reprocessed each time a change is made.
Disadvantages
1. Costly than compiler.
2. Those who want to run your program must have a suitable interpreter.
3. Less efficient than compilers because interpreted programs run more slowly than compiled programs. The reason behind slow execution is that interpreter takes one statement at a time rather than whole program like compiler.
4. It must be present on the machine as additional software to run the program.
5. No object code is produced, so a translation has to be done every time the program is running. Source code is required for the program to be executed.
HOW DOES COMPILER/INTERPRETER WORK?
Source File
This is the program that is read by the compiler or interpreter.
Scanner
This is the first module in a compiler or interpreter. Its job is to read the source file one character at a time. It can also keep track of which line number and character is currently being read. A typical scanner can be instructed to move backwards and forwards through the source file. Why do we need to move backwards? We will see why in just a little bit when we examine the lexer. For now, assume that each time the scanner is called; it returns the next character in the file.
Lexer
This module serves to break up the source file into chunks (called tokens). It calls the scanner to get characters one at a time and arranges them into tokens and token types. For instance, if the source file read something like this:
salary = hra + 1000;
print “Value of salary is“, salary;
A lexer would perhaps break it like this:
salary -> Identifier (variable)
= -> Symbol (assignment operator)
hra -> Identifier (variable)
+ -> Symbol (addition operator)
1000 -> Numeric constant
; -> Symbol (end of statement)
print -> Identifier (keyword)
“Value of salary is “ -> String constant
, -> Symbol (string concatenation operator)
salary -> Identifier (variable)
; -> Symbol (end of statement)
Thus, the lexer calls the scanner to pass it one character at a time and groups them together and identifies them up as tokens for the language parser (which is the next stage). It also identifies the type of token (variable vs. keyword, assignment operator vs. addition operator vs. string concatenation operator etc.) Occasionally, the lexer has to tell the scanner to back up though. Consider a language that has operators that may be more than one character long (! vs. !=, < vs. <=, + vs. ++ etc.) Assume that lexer has requested the scanner for a character and it has returned ‘<’. The lexer needs to identify whether the operator is a < or a <=. So it requests the scanner for another character. If the next character is a ‘=’, it changes the token to ‘<=’ and passes it to the parser. If not, it tells the scanner to back up one character and hold it in the buffer, while it passes the ‘<’ to the parser.
Parser
This is the part of the compiler that really understands the syntax of the language. It calls the lexer to get tokens and processes the tokens per the syntax of the language. The parser checks that the program is written correctly (according to the language rules). The parser reads in the tokens generated by the lexer and compares them to the set grammar of the programming language. If the program follows the rules of the language, then it is syntactically correct.
For instance, taking the example from the lexer above, the hypothetical interaction between the lexer and parser could go like this:
Parser: Give me the next token
Lexer: Next token is “salary“ which is variable
Parser: Ok, I have “salary” as a declared integer variable. Give me next token
Lexer: Next token is “=”, the assignment operator
Parser: Ok, program wants me to assign something to “salary”. Next token
Lexer: The next token is “hra” which is a variable
Parser: Ok, I know “hra” is an integer variable. Next token please
Lexer: The next token is “+”, which is an addition operator
Parser: Ok, so I need to add something to the value in “hra”. Next token please
Lexer: The next token is “1000”, which is an integer
Parser: Ok, both “hra” and “1000” are integers, so I can add them. Next token please
Lexer: The next token is “;” which is end of statement
Parser: Ok I will evaluate “hra + 1000” and get the answer
Parser: I will take the answer from “hra + 1000” and assign it to “salary”
In the above, the indenting shows a subprocess that the parser enters, to evaluate “hra + 1000”. This gives you decent idea about how the parser operates. Also note that the parser is checking types and syntax rules (for instance, it checked whether “hra” and “1000” were both integer types before adding them). If the parse gets a token that it was not expecting, it will stop processing and complain to the user about an error. The scanner holds the current line number and character, so the Parser can inform the user approximately where the error occurred.
Interpreter/Code generator
This is the part that actually takes the action that is specified by a program statement. In some cases, this is actually part of the parser (especially for interpreters) and the parser interprets and takes action directly. In other cases, the parser converts the statement into byte-code (intermediate language). In case of compiler for a different CPU or architecture, all you have to do is put a new code generator unit to translate the byte code into machine code for the new CPU.
LINKER AND LOADER
Linker
Software often consists of several thousands, even several millions, of lines of program code. For software of this size, it is impractical to store all the lines of program code in a single source program file due to the following reasons:
1. The large size of the file would make it very difficult, if not possible, to work with. For example, it might not be possible to load the file for compilation on a computer with limited main memory capacity. Again, while editing the file, it could be very tedious and time-consuming to locate a certain line of code.
2. It would make it difficult to deploy multiple programmers to work concurrently towards the development of the software for completing it within a specified time limit.
3. Any change in the source program, no matter how small, would require the entire source program to be recompiled. Recompilation of large source programs is often a time-consuming process.
To take care of these problems, a modular approach is generally adapted to develop reasonably sized software. In this approach, the software is divided into functional modules and separate source programs are written for each module of the software. Often there is no need to even write source programs for some of the modules because there might be programs available in a program library, which offer the same functionality. These library programs are maintained in their object code form.
When modular approach is used for developing software, the software consists of multiple source program files. Each source program file can be modified and compiled independent of other source program files to create a corresponding object program file. In this case, a program called a linker is used to properly combine all the object program files (modules) of the software, and to convert them into the final executable program, which is sometimes called a load module. That is, a linker takes object program files (modules) and fits them together to assemble them into the program’s final executable form.
The process of compiling the multiple source program files of modularly developed software and linking them to create the executable program (load module) is illustrated in Figure. Note that since converting the source programs into an executable program is a two-step process, when the software is modified, there is no need to recompile all the source programs. Rather, only the changed source programs need to be recompiled to produce new object programs for them. The linker can then be executed to create a new executable program by reassembling the newly created and the old object programs and library modules.
Linkers are supplied as a part of the development environment (which consists of a set of program development tools) of a computer system that includes a compiler. One can also purchase third-party linkers that can sometimes improve the performance of a program over the standard linkers provided as a part of the system’s development environment.
Loader
Loading means physically placing the machine instructions and data into main memory. A loader is a system program that accepts object programs and prepares them for execution and starts the execution. The functions of the loader are as follows:
· Assignment of load-time storage area to the program
· Loading of program into assigned area
· Relocation of program to execute properly from its load time storage area
· Linking of programs with one another
Thus, a loader is a program that places a program’s instructions and data into primary storage locations. An absolute loader places these items into the precise locations indicated in the machine language program. A relocating loader may load a program at various places in primary storage depending on the availability of primary storage area at the time of loading. A program may be relocated dynamically with the help of a relocating register. The base address of the program in primary storage is placed in the relocating register. The contents of the relocating register are added to each address developed by a running program. The user is able to execute the program as if it begins at location zero. At execution time, as the program runs, all address references involve the relocation register. This allows the program to reside in memory locations other than those for which it was translated to occupy.
Made By: Chaudhary Amit V.

Comments
Post a Comment