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+1
mean?- 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 -> bR
R -> 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