CS 330 Lecture 19 – A Logo REPL Part II
Agenda
- what ?s
- comments
- bugs
- a REPL
- variables
- expressions
General Test Topics
Things on the exam:
- addressable memory
- stack vs. heap storage
- pattern matching with common regex primitives
- types and type checking
- declarations vs. definitions
- basic instructions (pushl, movl, addl, subl) and flow control (cmpl, jmp and friends) in assembly
- big picture ideas
- small code exercises
- questions with gradable answers
- invocation of shell utilities and pipelines
Things not on the exam:
- addressing modes
- Japan’s geopolitical concerns
- cheese
- the answers
- Ruby, per se
- questions requiring a catalog of knowledge about shell utilities
Code
Logo.g4
grammar Logo;
program
: statement* EOF
;
statement
: command NEWLINE
;
command
: MOVE expression # Move
| TURN expression # Turn
| SLIME (ON | OFF) # Slime
| ID IS expression # Assignment
| ID # Echo
;
expression
: INT # Int
| ID # Reference
| '(' expression ')' # Parenthesized
| expression MULTIPLICATIVE_OPERATOR expression # MulDivMod
| expression ADDITIVE_OPERATOR expression # AddSub
;
MULTIPLICATIVE_OPERATOR : ('*'|'/'|'%');
ADDITIVE_OPERATOR : ('+'|'-');
IS : '<-';
MOVE : 'move';
TURN : 'turn';
SLIME : 'slime';
ON : 'on';
OFF : 'off';
INT : '-'? [0-9]+;
NEWLINE : '\r'? '\n';
ID : [A-Za-z_] [A-Za-z0-9_]*;
COMMENT : '#' .*? '\n' -> skip;
WHITESPACE : [ \t\r]+ -> skip;
makefile
Note to copy and pasters: makefile rules need to be indented with real tabs, not spaces.
ANTLR_JAR = $(HOME)/bin/antlr-4.0-complete.jar
ANTLR = java -jar $(ANTLR_JAR)
all: Interpreter.class
LogoParser.class: Logo.g4 makefile
$(ANTLR) Logo.g4
javac Logo*.java
Interpreter.class: LogoParser.class Interpreter.java
javac Interpreter.java
clean:
rm -f *.class Logo*.java *.tokens
square.logo
move 100
turn 90
move 100
turn 90
move 100
turn 90
move 100
varsquar.logo
angle <- 90
distance <- 100
move distance
turn angle
move distance
turn angle
move distance
turn angle
move distance
arithtest.logo
foobar <- 50 * 2 + 100
foobar
move foobar
Interpreter.java
import org.antlr.v4.runtime.*;
import java.util.HashMap;
import java.util.Stack;
import java.util.Scanner;
import java.util.ArrayList;
import java.io.IOException;
import org.antlr.v4.runtime.tree.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.AffineTransform;
public class Interpreter extends LogoBaseListener {
public static void main(String[] args) throws IOException {
Interpreter interpreter = new Interpreter();
interpreter.pause(1000);
ANTLRInputStream input = new ANTLRInputStream(System.in);
LogoLexer lexer = new LogoLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LogoParser parser = new LogoParser(tokens);
ParseTree tree = parser.program();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(interpreter, tree);
}
/* ------------------------------------------------------------------------- */
private ArrayList<Line2D.Double> segments = new ArrayList<Line2D.Double>();
private double x = 0.0;
private double y = 0.0;
private double theta = 0.0;
private boolean isLeaking = true;
private HashMap<String, Integer> variables = new HashMap<String, Integer>();
private Stack<Integer> stack = new Stack<Integer>();
public void exitMove(LogoParser.MoveContext context) {
double distance = stack.pop();
double newX = x + distance * Math.cos(theta);
double newY = y + distance * Math.sin(theta);
if (isLeaking) {
segments.add(new Line2D.Double(x, y, newX, newY));
}
x = newX;
y = newY;
}
public void exitTurn(LogoParser.TurnContext context) {
theta += Math.toRadians(stack.pop());
}
public void exitAssignment(LogoParser.AssignmentContext context) {
String name = context.ID().getText();
variables.put(name, stack.pop());
}
public void exitSlime(LogoParser.SlimeContext context) {
isLeaking = context.ON() != null;
}
public void exitInt(LogoParser.IntContext context) {
stack.push(Integer.parseInt(context.INT().getText()));
}
public void exitReference(LogoParser.ReferenceContext context) {
String name = context.ID().getText();
stack.push(variables.get(name));
}
public void exitEcho(LogoParser.EchoContext context) {
String id = context.ID().getText();
System.out.println(id + ": " + variables.get(id));
}
public void exitAddSub(LogoParser.AddSubContext context) {
int b = stack.pop();
int a = stack.pop();
if (context.ADDITIVE_OPERATOR().getText().equals("+")) {
stack.push(a + b);
} else {
stack.push(a - b);
}
}
public void exitMulDivMod(LogoParser.MulDivModContext context) {
int b = stack.pop();
int a = stack.pop();
if (context.MULTIPLICATIVE_OPERATOR().getText().equals("*")) {
stack.push(a * b);
} else if (context.MULTIPLICATIVE_OPERATOR().getText().equals("/")) {
stack.push(a / b);
} else {
stack.push(a % b);
}
}
/* ------------------------------------------------------------------------- */
public void enterStatement(LogoParser.StatementContext context) {
System.out.println("about to execute " + context.getText());
}
public void exitEveryRule(ParserRuleContext context) {
pause(500);
display.repaint();
}
private void pause(int delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
private LogoDisplay display;
public Interpreter() {
JFrame frame = new JFrame("Logo");
display = new LogoDisplay();
frame.setContentPane(display);
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class LogoDisplay extends JPanel {
private Line2D.Double arrowTop;
private Line2D.Double arrowBottom;
public LogoDisplay() {
arrowTop = new Line2D.Double(-10.0f, -5.0f, 0.0f, 0.0f);
arrowBottom = new Line2D.Double(-10.0f, 5.0f, 0.0f, 0.0f);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform xform = g2.getTransform();
g2.translate(100, 100);
for (Line2D.Double segment : segments) {
g2.draw(segment);
}
g2.translate(x, y);
g2.rotate(theta);
g2.draw(arrowTop);
g2.draw(arrowBottom);
}
}
}
Haiku
Technology chills?
Machines are impersonal?
My numbers are named
Machines are impersonal?
My numbers are named