Compilers Overview
Lecture 2
Table of Contents
Review
- What is a compiler?
- Compilers vs. interpreters
- Symbols vs. meaning
Questions about the last class?
- Dragon book pg55 (2.3.2) pg69 (2.5)
How would you describe C?
- Someone asks you to explain how the C language works
- How would you do it?
- What do arithmetic operations do?
- What does
x=2+1; x=x+1mean?- Contradicts traditional math equality
- What do loops do?
Translating to postfix
- Input: three times two plus one
- Output: 3 2 * 1 +
Defining the syntax
expression -> expression operator number expression -> number number -> one number -> two ... number -> nine operator -> plus operator -> times
expression -> expression operator number
{ expression0.value = concat(expression1.value, number.value, operator.value) }
expression -> number { expression.value = number.value }
number -> one { number.value = "1" }
number -> two { number.value = "2" }
...
number -> nine { number.value = "9" }
operator -> plus { operator.value = "+" }
operator -> times { operator.value = "*" }
Defining the translation over the syntax
- Start with syntax
- Define semantic rules (Dragon Book 2.3.2)
- "Code" executed after each syntactic rule is matched
- Store "return values" for parent syntax to use
- Examples
- number -> nine { print "9" }
- operator -> plus { operator.value = "+" }
expression -> expression operator number { expression.value = concat(expression.value, number.value, operator.value) }
expression -> number { expression.value = number.value }
number -> one { number.value = "1" }
number -> two { number.value = "2" }
...
number -> nine { number.value = "9" }
operator -> plus { operator.value = "+" }
operator -> times { operator.value = "*" }
Example
Input: three times two plus one
Steps:
- expression(three times two plus one) -> expression(three times two) operator(plus) number(one)
{ expression.value = concat("32*, "1", "+") -> "32*1+"
- expression(three times two) -> expression(three) operator(times) number(two) { expression.value = concat("3", "2", "*") = "32*" }
- expression(three) -> number(three) { expression.value = "3" }
- number(three) -> three { number.value = "3" }
- operator(times) -> times { operator.value = "*" }
- number(two) -> two { number.value = "2" }
- operator(plus) -> plus { operator.value = "+" }
- number(one) -> one { number.value = "1" }
Output: 32*1+
Steps
- expression(three times two plus one) -> expression(three times two) operator(plus) number(one) { value "3 2 * 2 +" }
- expression(three times two) -> expression(three) operator(times) number(two) { value = "3 2 *) }
- expression(three) -> number(three) { value = "3" }
- number(three) -> three { value = "3" }
- operator(times) -> times { value = "*" }
- number(two) -> two { value = "2" }
- expression(three) -> number(three) { value = "3" }
- operator(plus) -> plus { value = "+" }
- number(one) -> two { value = "2" }
- expression(three times two) -> expression(three) operator(times) number(two) { value = "3 2 *) }
Python program
- Recursive descent, predictive parser
- One function per nonterminal
- Lookahead to check which alternative to follow
- Left recursion elimination (Dragon Book 2.4.5)
- Left recursion:
A -> Aa | b - Equivalent without left recursion
A -> bRR -> aR | empty
- Left recursion:
import sys
import os
nums = { "zero" : "1",
"one" : "1",
"two" : "2",
"three" : "3",
"four" : "4",
"five" : "5",
"six" : "6",
"seven" : "7",
"eight" : "8",
"nine" : "9",
}
ops = { "plus" : "+",
"times" : "*",
"minus" : "-",
"divide" : "/",
}
def expression(words):
n = number(words)
r = rest(words)
return n + r
def rest(words):
lookahead = words.pop(0)
words.insert(0, lookahead)
if (lookahead in ops.keys()):
o = operator(words)
n = number(words)
r = rest(words)
return n + o + r
else:
return ""
def number(words):
return nums[words.pop(0)]
def operator(words):
return ops[words.pop(0)]
x = input("input string of words: ")
words = x.split(" ")
words.append("$")
print(expression(words))
Order of operations?
Homework
- Setup ANTLR and test out your setup
- Start with the LabeledExpr grammar
- Download ANTLR examples
- Start with code/tour/LabeledExpr.g4 and code/tour/Calc.java
- Ask questions on slack for support
Building and running the ANTLR
# add antlr to your classpath; your path to the runtime may vary export CLASSPATH=/usr/share/java/antlr4-runtime.jar:$CLASSPATH # this generates the parser antlr4 -visitor LabeledExpr.g4 # this compiles the calculator javac LabeledExpr*.java Calc.java EvalVisitor.java # write an expression to stdin or pass a file java Calc # use this to display a parse tree, remove -gui if os is headless /usr/share/antlr4/grun LabeledExpr prog -gui