A compiler translates a high-level program into machine code in phases, each transforming one representation into the next. Lexical analysis groups characters into tokens: keywords, identifiers, numbers, operators and punctuation. Syntax analysis checks that tokens follow the grammar and builds a parse tree. Semantic analysis checks meaning: types, declarations and scope. Intermediate code generation produces a machine-independent form, usually three-address code. Optimisation improves it without changing meaning. Code generation produces target machine code, using registers and the symbol table throughout.
The first two phases are the most examined. A lexeme is the actual character sequence (for example "total"), and its token is its category (identifier). The parser's job is not just to accept or reject: it builds the tree that later phases use. A grammar is ambiguous when some string has two different parse trees, which makes meaning uncertain — the classic example is the dangling else, where an else could belong to either of two ifs.
Worked example — three-address code. For the statement a = b c + d, the compiler breaks it into steps with at most one operator each: t1 = b c; t2 = t1 + d; a = t2. Temporary variables t1 and t2 hold intermediate values. This form is easy to optimise: if b and c are constants, t1 can be folded at compile time; if t2 is never used elsewhere, its computation may be eliminated. Three-address code is the bridge between the tree and the machine.