Syntax-directed translation A Simple Ompass Compiler
🧠 What Does “Syntax-Directed” Really Mean?
Let’s take a simple idea:
- When a compiler sees an addition like
a + 3,
it should compute or generate code for that. - When it sees an assignment like
x = ...,
it should store the result.
Every piece of work the compiler does is attached to a rule in the syntax.
So, the syntax (grammar) decides the structure,
and the translation rules decide the meaning or action.
It’s like:
- Grammar = the skeleton
- Translation rules = the muscles that move the skeleton
Both work together.
🧩 How Syntax-Directed Translation Works (Friendly Breakdown)
Let’s create a tiny Ompass language again, just like earlier:
- It supports assignments
- It allows arithmetic expressions
- It uses variables and numbers
Here’s a simple grammar, but this time with translation rules added:
<statement> → <id> = <expression> { print("assign " + id.name) }
<expression> → <expression> + <term> { print("add") }
<expression> → <expression> - <term> { print("sub") }
<expression> → <term>
<term> → <term> * <factor> { print("mul") }
<term> → <term> / <factor> { print("div") }
<term> → <factor>
<factor> → <number> { print("push " + number.value) }
<factor> → <id> { print("push " + id.name) }
<factor> → ( <expression> )
Don’t worry about the code in curly braces — it simply describes what the compiler does when that rule matches.
For example:
- When it sees a number like
7, the rule says:
→ push 7
meaning: “Store this value for later use.” - When it sees
+, the rule says:
→ add
meaning: “Combine the top two values.”
This is the heart of syntax-directed translation.
Translation
Let’s translate this tiny program:
x = a + 3
What happens?
- The compiler sees
a → push a - Then sees
3 → push 3 - Then sees
+ → add - Then the assignment rule prints
assign x
So the final output (or intermediate code) looks like:
push a
push 3
add
assign x
This is how a simple Ompass compiler would understand and translate code.
🌳 Diagram: Syntax-Directed Translation Tree
Below is a simple, hand-drawn style diagram showing how translation happens alongside the parse tree.
<statement>
|
--------------------------------------------------
| |
<id> <expression>
| |
x ----------------------------------------
| |
<expression> + <term>
| |
<term> <factor>
| |
<factor> 3
|
a
Attached translation actions (shown in order they fire):
push a
push 3
add
assign x
The compiler processes the tree bottom-up.
As it reaches each node, it triggers the action connected to that rule.
🧩 Why Syntax-Directed Translation Is Important
Syntax-directed translation helps a compiler:
✔ generate intermediate code
✔ evaluate expressions
✔ type-check values
✔ build symbol tables
✔ simplify later stages like optimization and code generation
It’s like giving the compiler a map that says:
“Whenever you see this, produce that.”
This keeps everything organized and predictable.
