हिंदी में: कंपाइलर हमारे लिखे कोड को मशीन की भाषा में कैसे बदलता है — चरण दर चरण।
Compilers, interpreters and friends
- A compiler translates the whole source program into a target language (often machine code) before it runs — e.g. GCC for C.
- An interpreter executes the program statement by statement — e.g. the CPython interpreter.
- An assembler converts assembly language into machine code; a linker joins object files and libraries; a loader places the program in memory to run.
- Java uses both:
javaccompiles to bytecode, and the JVM interprets and JIT-compiles it.
Phases of a compiler
| Phase | Input → Output | What it does |
|---|---|---|
| Lexical analysis | Characters → tokens | Groups characters into tokens (keywords, identifiers, numbers, operators); removes whitespace and comments |
| Syntax analysis (parsing) | Tokens → parse tree | Checks the grammar of the language |
| Semantic analysis | Parse tree → annotated tree | Type checking, scope rules, declared-before-use |
| Intermediate code generation | Tree → IR | Produces machine-independent code such as three-address code |
| Code optimization | IR → better IR | Makes code faster or smaller without changing meaning |
| Code generation | IR → target code | Chooses instructions and allocates registers |
The symbol table (storing names, types and scopes) and the error handler are used by every phase. The first phases form the front end (language-dependent); the later ones form the back end (machine-dependent).
Example
For total = price + rate * 10, the lexer produces tokens such as id(total) = id(price) + id(rate) * num(10). The parser builds a tree where * binds tighter than +. Three-address code might be:
t1 = rate * 10
t2 = price + t1
total = t2
Lexical analysis
Token patterns are described with regular expressions and recognised with finite automata. Tools such as Lex/Flex generate lexers automatically.
Parsing
Top-down parsers build the tree from the start symbol: – Recursive descent, and LL(1) predictive parsing using FIRST and FOLLOW sets. – The grammar must have no left recursion and must be left-factored.
Bottom-up parsers reduce the input back to the start symbol (shift–reduce): – LR(0), SLR(1), LALR(1), CLR(1) — in increasing power. LALR(1) is used by Yacc/Bison.
Syntax-directed translation
Semantic rules attached to grammar productions compute attributes: – Synthesized attributes take values from children. – Inherited attributes take values from the parent or siblings.
Code optimization techniques
- Constant folding:
x = 2 * 3→x = 6. - Common subexpression elimination: compute
a + bonce and reuse it. - Dead code elimination: remove code whose result is never used.
- Loop optimizations: move loop-invariant code out of loops, strength reduction (replace
*with+), loop unrolling. - Peephole optimization: improve short sequences of target instructions.
Runtime environment
Activation records on the stack hold parameters, local variables and return addresses for each function call; dynamically allocated objects live on the heap.
Quick revision
- Lexer → parser → semantic analyser → IR → optimizer → code generator.
- LL parsers are top-down; LR parsers are bottom-up.
- LR(0) ⊂ SLR(1) ⊂ LALR(1) ⊂ CLR(1) in power.
- Three-address code has at most one operator on the right-hand side.