
- Compiler Design - Home
- Compiler Design - Overview
- Compiler Design - Architecture
- Phases
- Compiler Design - Phases
- Compiler Design - Global Optimization
- Compiler Design - Local Optimization
- Lexical Analysis
- Compiler Design - Lexical Analysis
- Compiler Design - Regular Expressions
- Compiler Design - Finite Automata
- Compiler Design - Language Elements
- Compiler Design - Lexical Tokens
- Compiler Design - FSM
- Compiler Design - Lexical Table
- Compiler Design - Sequential Search
- Compiler Design - Binary Search Tree
- Compiler Design - Hash Table
- Syntax Analysis
- Compiler Design - Syntax Analysis
- Compiler Design - Parsing Types
- Compiler Design - Grammars
- Compiler Design - Classes Grammars
- Compiler Design - Pushdown Automata
- Compiler Design - Ambiguous Grammar
- Parsing
- Compiler Design - Top-Down Parser
- Compiler Design - Bottom-Up Parser
- Compiler Design - Simple Grammar
- Compiler Design - Quasi-Simple Grammar
- Compiler Design - LL(1) Grammar
- Error Recovery
- Compiler Design - Error Recovery
- Semantic Analysis
- Compiler Design - Semantic Analysis
- Compiler Design - Symbol Table
- Run Time
- Compiler Design - Run-time Environment
- Code Generation
- Compiler Design - Code Generation
- Converting Atoms to Instructions
- Compiler Design - Transfer of Control
- Compiler Design - Register Allocation
- Forward Transfer of Control
- Reverse Transfer of Control
- Code Optimization
- Compiler Design - Code Optimization
- Compiler Design - Intermediate Code
- Basic Blocks and DAGs
- Control Flow Graph
- Compiler Design - Peephole Optimization
- Implementing Translation Grammars
- Compiler Design - Attributed Grammars
Implementing Translation Grammars in Compiler Design
Parsing is a key topic in compiler design. There are different types of parsers, including top-down and bottom-up parsers. In top-down parsing, syntax-directed translation plays an important role. Unlike regular grammars, translation grammars not only focus on syntax but also include action symbols that perform tasks like output generation or function calls. These grammars help the compiler convert code into an intermediate representation, which is essential for optimization and execution.
In this chapter, we will explore translation grammars, understand their structure, and look at examples for better understanding.
What is a Translation Grammar?
Translation grammar is a special type of grammar that includes action symbols. This grammar is written in {curly braces}, to produce output or call functions while parsing an input string.
To implement translation grammars, we generally use pushdown translators or recursive descent translators. These techniques are used to convert infix expressions to postfix notation. They generate machine instructions, and simplify expression evaluation.
Key Characteristics of Translation Grammars
Let us see some of the key characteristics of translation grammars −
- Action Symbols − These are special symbols {A}, and this is used to generate output or perform operations.
- Underlying Grammar − The same grammar without the action symbols is called the underlying grammar.
- Epsilon Rules − Rules like A → {action} are treated as epsilon (ε) rules in the underlying grammar.
Translation Grammar for Infix to Postfix Conversion
Consider the grammar G1, which translates infix expressions to postfix notation −
- Expr → Term Elist
- Elist → + Term {+} Elist
- Elist → ε
- Term → Factor Tlist
- Tlist → * Factor {*} Tlist
- Tlist → ε
- Factor → ( Expr )
- Factor → var {var}
Here we can see how this grammar processes an expression like var + var * var −
var {var} + var {var} * var {var} {*} {+}
The output string is −
{var} {var} {var} {*} {+}
Here, we get the postfix (Reverse Polish) notation for the given infix expression.

Implementing Translation Grammars Using Pushdown Translators
A pushdown translator is like push-down automata or we can say this is an extended pushdown machine that treats action symbols just like terminals and non-terminals.
Steps to Implement a Pushdown Translator −
- Push action symbols onto the stack as if they were regular grammar symbols.
- When an action symbol is encountered, output the corresponding action.
- Pop the stack when rules are applied just like in normal parsing.
Pushdown Translator Table for Grammar G1
From this table, each action symbol generates output at the right time. This is preserving postfix order.
Input | Stack Action | Output |
---|---|---|
var | {var} Retain | {var} |
+ | Pop | + |
* | Pop | * |
Implementing Translation Grammars Using Recursive Descent Translators
Another method could be a recursive descent translator processes to translate grammars using function calls. When an action symbol is encountered, it is either printed or triggers a function call.
Example: Recursive Descent Parser for Grammar G1
Here is how a recursive descent function would process expressions −
void Expr() { if (inp == '(' || inp == var) { Term(); Elist(); } else Reject(); } void Elist() { if (inp == '+') { getInp(); // Move to next token Term(); System.out.println('+'); Elist(); } else if (inp == Endmarker || inp == ')'); // Rule 3 (epsilon rule) else Reject(); } void Term() { if (inp == '(' || inp == var) { Factor(); Tlist(); } else Reject(); } void Tlist() { if (inp == '*') { getInp(); Factor(); System.out.println('*'); Tlist(); } else if (inp == '+' || inp == ')' || inp == Endmarker); // Rule 6 (epsilon rule) else Reject(); } void Factor() { if (inp == '(') { getInp(); Expr(); if (inp == ')') getInp(); else Reject(); } else if (inp == var) { getInp(); System.out.println("var"); } else Reject(); }
Let's now understand how it works −
- When a + is encountered, it prints + to move it to postfix.
- When a * is encountered, it prints * at the correct moment.
- Variables (var) are printed as they appear.
For var + var * var, this parser correctly translates it to postfix −
var var var * +
Pushdown Translators vs Recursive Descent Translators
The following table compares and contrasts and pros and cons of Pushdown Translators and Recursive Descent Translators −
Method | Pros | Cons |
---|---|---|
Pushdown Translator | Works well with stack-based parsing | Complex to implement manually |
Recursive Descent | Easier to implement and debug | May require extra checks for actions |
Pushdown translators are often used in automated compiler tools, but recursive descent is more common in hand-written parsers.
Applications of Translation Grammars
Translation grammars are useful and it has a key role in the following:
- Code Generation − Converting high-level code into an intermediate representation (IR).
- Syntax-Directed Translation − Transforming source code into optimized machine instructions.
- Expression Evaluation − Converting infix to postfix or prefix notation.
- Compiler Construction − Used in parsers and interpreters.
Example: Translating a Custom Expression
Consider the following expression −
(a + b) * c
Using grammar G1, the translation follows the steps shown below. The Derivation Tree looks like this −

The generated Postfix Expression is −
a b + c *
It demonstrates how action symbols correctly reorder expressions using translation grammars.
From this, we can get a detailed concept and we can remember them through the following table −
Concept | Explanation |
---|---|
Action Symbols | { } symbols that trigger output or function calls. |
Underlying Grammar | The same grammar without action symbols. |
Pushdown Translator | Uses stack-based parsing to output translation symbols. |
Recursive Descent Translator | Uses function calls to generate translation. |
Postfix Notation | Ensures correct operator precedence. |
Conclusion
In this chapter, we explored translation grammars and their role in compiler design. We covered pushdown translators and recursive descent translators, which help convert infix expressions to postfix notation.
Through examples, we saw how action symbols guide code translation, optimize parsing, and improve expression evaluation. Translation grammars are essential in syntax-directed translation, helping transform source code into an efficient intermediate representation for compilation.