CS 330 Lecture 30 – Logo Translation
Agenda
- what ?s
- writing a translator for Logo
- think about this
TODO
- Extra credit 1/4 sheet: Write a Logo program to demo in class. Download the Eclipse project. In Compiler.java, change the file name to point to your file, or use the JFileChooser. To receive credit, post the Logo source in the comments.
Think About This
- When a function is called, what environment should it operate under?
Code
Logo.g
grammar Logo;
program
: block EOF
;
block
: (command NEWLINE)*
;
command
: MOVE expression # Move
| ROTATE expression # Rotate
| REPEAT expression NEWLINE block END # Repeat
| LOG expression # Log
| IF expression NEWLINE block ELSE NEWLINE block END # If
| TO ID ID* EQUALS NEWLINE block END # Define
| ID expression* # Call
| ID EQUALS expression # Assignment
| PEN expression # Pen
;
expression
: LEFT_PARENTHESIS expression RIGHT_PARENTHESIS # Grouped
| expression POWER_OPERATOR expression # Power
| expression MULTIPLICATIVE_OPERATOR expression # Multiply
| expression ADDITIVE_OPERATOR expression # Add
| LITERAL # Literal
| ID # Identifier
;
// Keywords
TO: 'to';
LOG: 'log';
REPEAT: 'repeat';
END: 'end';
IF: 'if';
ELSE: 'else';
MOVE: 'move';
ROTATE: 'rotate';
PEN: 'pen';
EQUALS: '=';
LEFT_PARENTHESIS: '(';
RIGHT_PARENTHESIS: ')';
POWER_OPERATOR: '^';
MULTIPLICATIVE_OPERATOR: [*/];
ADDITIVE_OPERATOR: [-+];
LITERAL: '-'? [0-9]+ ('.' [0-9]+)?;
ID: [a-z]+;
WHITESPACE: [ \t]+ -> skip;
NEWLINE: '\r'? '\n';
makefile
Note to copy and pasters: makefile rules need to be indented with real tabs, not spaces.
ANTLR = $(HOME)/bin/antlr-4.1-complete.jar
CP = -cp $(ANTLR):.
all: LogoParser.java LogoLexer.java
LogoParser.java LogoLexer.java: Logo.g makefile
java -jar $(ANTLR) -package logo330.antlr Logo.g
LogoParser.class LogoLexer.class: LogoParser.java LogoLexer.java makefile
javac $(CP) LogoLexer.java LogoParser.java
# InterpreterLogo.class: InterpreterLogo.java LogoParser.class LogoLexer.class
# javac $(CP) InterpreterLogo.java
run:
java $(CP) InterpreterLogo
clean:
rm -f *.class *.tokens LogoLexer.java LogoParser.java
hernagon.logo
to poly n size =
repeat n
move size
rotate 180 - (360 / n)
end
end
poly 12 50
hernagon2.logo
to poly n size =
repeat n
move size
rotate 360 / n
end
end
n = 3
repeat 40
poly n 30
n = n + 1
end
lewis.logo
move 10
repeat 9
rotate 18
move 61
end
movemovemove.logo
move 10
move 20
move 30
polyf.logo
to poly n size =
theta = 360 / n
repeat n
move size
rotate theta
end
end
n = 3
repeat 50
poly n 10
n = n + 1
end
recursion.logo
to square size =
rotate 90
repeat 4
move size
rotate 90
end
end
to recurse n =
log n
if n
square n
recurse n - 5
else
log -1
end
end
recurse 100
square.logo
repeat 4
move 10
rotate 90
end
square_list.logo
move 10
rotate 90
move 10
rotate 90
move 10
rotate 90
move 10
rotate 90
squaref.logo
to square size =
repeat 4
move size
rotate 90
end
end
square 50
Logo.tokens
NEWLINE=19
RIGHT_PARENTHESIS=12
TO=1
MOVE=7
LOG=2
LEFT_PARENTHESIS=11
PEN=9
ELSE=6
WHITESPACE=18
LITERAL=16
REPEAT=3
EQUALS=10
ROTATE=8
POWER_OPERATOR=13
MULTIPLICATIVE_OPERATOR=14
ID=17
ADDITIVE_OPERATOR=15
END=4
IF=5
'end'=4
'pen'=9
'else'=6
'to'=1
'log'=2
'rotate'=8
'repeat'=3
'='=10
'if'=5
'('=11
')'=12
'^'=13
'move'=7
LogoLexer.tokens
NEWLINE=19
RIGHT_PARENTHESIS=12
TO=1
MOVE=7
LOG=2
LEFT_PARENTHESIS=11
PEN=9
ELSE=6
WHITESPACE=18
LITERAL=16
REPEAT=3
EQUALS=10
ROTATE=8
POWER_OPERATOR=13
MULTIPLICATIVE_OPERATOR=14
ID=17
ADDITIVE_OPERATOR=15
END=4
IF=5
'end'=4
'pen'=9
'else'=6
'to'=1
'log'=2
'rotate'=8
'repeat'=3
'='=10
'if'=5
'('=11
')'=12
'^'=13
'move'=7
Block.java
package logo330;
import java.util.ArrayList;
import logo330.command.Command;
public class Block {
private ArrayList<Command> commands = new ArrayList<Command>();
public void execute(Environment env) {
for (Command command : commands) {
command.execute(env);
}
}
public void add(Command command) {
commands.add(command);
}
public int size() {
return commands.size();
}
}
Compiler.java
package logo330;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Stack;
import javax.swing.JFileChooser;
import logo330.antlr.LogoBaseListener;
import logo330.antlr.LogoLexer;
import logo330.antlr.LogoParser;
import logo330.antlr.LogoParser.AddContext;
import logo330.antlr.LogoParser.AssignmentContext;
import logo330.antlr.LogoParser.BlockContext;
import logo330.antlr.LogoParser.CallContext;
import logo330.antlr.LogoParser.DefineContext;
import logo330.antlr.LogoParser.IdentifierContext;
import logo330.antlr.LogoParser.IfContext;
import logo330.antlr.LogoParser.LiteralContext;
import logo330.antlr.LogoParser.LogContext;
import logo330.antlr.LogoParser.MoveContext;
import logo330.antlr.LogoParser.MultiplyContext;
import logo330.antlr.LogoParser.PenContext;
import logo330.antlr.LogoParser.PowerContext;
import logo330.antlr.LogoParser.ProgramContext;
import logo330.antlr.LogoParser.RepeatContext;
import logo330.antlr.LogoParser.RotateContext;
import logo330.command.CommandAssignment;
import logo330.command.CommandFunctionCall;
import logo330.command.CommandFunctionDefine;
import logo330.command.CommandIf;
import logo330.command.CommandLog;
import logo330.command.CommandMove;
import logo330.command.CommandPen;
import logo330.command.CommandRepeat;
import logo330.command.CommandRotate;
import logo330.expression.Expression;
import logo330.expression.ExpressionAdd;
import logo330.expression.ExpressionDivide;
import logo330.expression.ExpressionIdentifier;
import logo330.expression.ExpressionLiteral;
import logo330.expression.ExpressionMultiply;
import logo330.expression.ExpressionSubtract;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
public class Compiler extends LogoBaseListener {
public static void main(String[] args) throws FileNotFoundException, IOException {
File f = new File("/Users/johnch/Desktop/recursion.logo");
if (f == null) {
JFileChooser chooser = new JFileChooser();
int ok = chooser.showOpenDialog(null);
if (ok == JFileChooser.APPROVE_OPTION) {
f = chooser.getSelectedFile();
}
}
ANTLRInputStream ais = new ANTLRInputStream(new FileInputStream(f));
LogoLexer lexer = new LogoLexer(ais);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LogoParser parser = new LogoParser(tokens);
ParseTree tree = parser.program();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new Compiler(), tree);
}
@Override
public void exitProgram(ProgramContext ctx) {
Environment env = new Environment();
Block main = blocks.pop();
new LogoVirtualMachine(env, main);
}
private Stack<Expression> operands = new Stack<Expression>();
private Stack<Block> blocks = new Stack<Block>();
public void enterBlock(LogoParser.BlockContext context) {
blocks.push(new Block());
}
public void exitIdentifier(IdentifierContext context) {
operands.push(new ExpressionIdentifier(context.ID().getText()));
}
public void exitLiteral(LiteralContext context) {
double value = Double.parseDouble(context.LITERAL().getText());
operands.push(new ExpressionLiteral(value));
}
@Override
public void exitCall(CallContext ctx) {
ArrayList<Expression> actualParameters = new ArrayList<Expression>();
for (int i = 0; i < ctx.expression().size(); ++i) {
actualParameters.add(0, operands.pop());
}
blocks.peek().add(new CommandFunctionCall(ctx.ID().getText(), actualParameters));
}
@Override
public void exitAssignment(AssignmentContext ctx) {
Expression e = operands.pop();
String id = ctx.ID().getText();
blocks.peek().add(new CommandAssignment(id, e));
}
@Override
public void exitBlock(BlockContext ctx) {
}
@Override
public void exitMultiply(MultiplyContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
if (ctx.MULTIPLICATIVE_OPERATOR().getText().equals("*")) {
operands.push(new ExpressionMultiply(a, b));
} else {
operands.push(new ExpressionDivide(a, b));
}
}
@Override
public void exitLog(LogContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandLog(e));
}
@Override
public void exitPen(PenContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandPen(e));
}
@Override
public void exitAdd(AddContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
if (ctx.ADDITIVE_OPERATOR().getText().equals("+")) {
operands.push(new ExpressionAdd(a, b));
} else {
operands.push(new ExpressionSubtract(a, b));
}
}
@Override
public void exitMove(MoveContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandMove(e));
}
@Override
public void exitRotate(RotateContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandRotate(e));
}
@Override
public void exitDefine(DefineContext ctx) {
ArrayList<String> formalParameters = new ArrayList<String>();
for (int i = 1; i < ctx.ID().size(); ++i) {
formalParameters.add(ctx.ID(i).getText());
}
System.out.println(formalParameters);
Block block = blocks.pop();
blocks.peek().add(new CommandFunctionDefine(ctx.ID(0).getText(), formalParameters, block));
}
@Override
public void exitIf(IfContext ctx) {
Block elseBlock = blocks.pop();
Block thenBlock = blocks.pop();
blocks.peek().add(new CommandIf(operands.pop(), thenBlock, elseBlock));
}
@Override
public void exitRepeat(RepeatContext ctx) {
Block block = blocks.pop();
blocks.peek().add(new CommandRepeat(operands.pop(), block));
}
@Override
public void exitPower(PowerContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
operands.push(new ExpressionAdd(a, b));
}
}
Environment.java
package logo330;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.HashMap;
import logo330.command.CommandListener;
public class Environment {
public double x = 0.0;
public double y = 0.0;
public double theta = 0.0;
public boolean isDrawing = true;
public HashMap<String, Double> locals = new HashMap<String, Double>();
public HashMap<String, Function> functions = new HashMap<String, Function>();
public ArrayList<Line2D.Double> segments = new ArrayList<Line2D.Double>();
public CommandListener listener = null;
}
Function.java
package logo330;
import java.util.ArrayList;
public class Function {
private String id;
private ArrayList<String> formalParameters;
private Block body;
public Function(String id, ArrayList<String> formalParameters, Block body) {
this.id = id;
this.formalParameters = formalParameters;
this.body = body;
}
public String getID() {
return id;
}
public ArrayList<String> getFormalParameters() {
return formalParameters;
}
public Block getBody() {
return body;
}
}
LogoVirtualMachine.java
package logo330;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import logo330.command.Command;
import logo330.command.CommandFunctionCall;
import logo330.command.CommandFunctionDefine;
import logo330.command.CommandListener;
import logo330.command.CommandMove;
import logo330.command.CommandRepeat;
import logo330.command.CommandRotate;
import logo330.expression.Expression;
import logo330.expression.ExpressionIdentifier;
import logo330.expression.ExpressionLiteral;
public class LogoVirtualMachine implements CommandListener {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
// Environment env = new Environment();
//
// Block main = new Block();
// main.add(new CommandMove(new ExpressionLiteral(24.0)));
// main.add(new CommandRotate(new ExpressionLiteral(90.0)));
// main.add(new CommandMove(new ExpressionLiteral(24.0)));
// main.add(new CommandRotate(new ExpressionLiteral(90.0)));
// main.add(new CommandMove(new ExpressionLiteral(24.0)));
// main.add(new CommandRotate(new ExpressionLiteral(90.0)));
// main.add(new CommandMove(new ExpressionLiteral(24.0)));
// main.add(new CommandRotate(new ExpressionLiteral(90.0)));
// Block body = new Block();
// body.add(new CommandMove(new ExpressionIdentifier("$size")));
// body.add(new CommandRotate(new ExpressionLiteral(90.0)));
// Command repeat = new CommandRepeat(new ExpressionLiteral(4), body);
//
// body = new Block();
// body.add(repeat);
//
// ArrayList<String> formalParameters = new ArrayList<String>();
// formalParameters.add("$size");
// Command c = new CommandFunctionDefine("square", formalParameters, body);
//
// c.execute(env);
//
// ArrayList<Expression> actualParameters = new ArrayList<Expression>();
// actualParameters.add(new ExpressionLiteral(150));
//
// main.add(new CommandFunctionCall("square", actualParameters));
Environment env = new Environment();
Block main = new Block();
new LogoVirtualMachine(env, main);
}
private JFrame display;
private JPanel panel;
private int delay = 40;
public LogoVirtualMachine(Environment env,
Block main) {
env.listener = this;
display = new JFrame("Logo");
panel = new LogoDisplay(env);
JScrollPane scroller = new JScrollPane(panel);
display.setContentPane(scroller);
panel.setPreferredSize(new Dimension(3000, 3000));
panel.setSize(panel.getPreferredSize());
display.setSize(1200, 700);
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
display.setVisible(true);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
main.execute(env);
}
public void onPostCommand() {
pause();
panel.paintImmediately(0, 0, panel.getWidth(), panel.getHeight());
}
private void pause() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
}
}
class LogoDisplay extends JPanel {
private Line2D.Double arrowTop;
private Line2D.Double arrowBottom;
private Environment env;
public LogoDisplay(Environment env) {
this.env = env;
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(1200 / 2, 700 / 2);
synchronized (env.segments) {
for (Line2D.Double segment : env.segments) {
g2.draw(segment);
}
}
g2.translate(env.x, env.y);
g2.rotate(env.theta);
g2.draw(arrowTop);
g2.draw(arrowBottom);
g2.setTransform(xform);
}
}
}
OldCompiler.java
package logo330;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Stack;
import javax.swing.JFileChooser;
import logo330.antlr.LogoBaseListener;
import logo330.antlr.LogoLexer;
import logo330.antlr.LogoParser;
import logo330.antlr.LogoParser.AddContext;
import logo330.antlr.LogoParser.AssignmentContext;
import logo330.antlr.LogoParser.BlockContext;
import logo330.antlr.LogoParser.CallContext;
import logo330.antlr.LogoParser.DefineContext;
import logo330.antlr.LogoParser.IdentifierContext;
import logo330.antlr.LogoParser.IfContext;
import logo330.antlr.LogoParser.LiteralContext;
import logo330.antlr.LogoParser.LogContext;
import logo330.antlr.LogoParser.MoveContext;
import logo330.antlr.LogoParser.MultiplyContext;
import logo330.antlr.LogoParser.PenContext;
import logo330.antlr.LogoParser.PowerContext;
import logo330.antlr.LogoParser.ProgramContext;
import logo330.antlr.LogoParser.RepeatContext;
import logo330.antlr.LogoParser.RotateContext;
import logo330.command.CommandAssignment;
import logo330.command.CommandFunctionCall;
import logo330.command.CommandFunctionDefine;
import logo330.command.CommandIf;
import logo330.command.CommandLog;
import logo330.command.CommandMove;
import logo330.command.CommandPen;
import logo330.command.CommandRepeat;
import logo330.command.CommandRotate;
import logo330.expression.Expression;
import logo330.expression.ExpressionAdd;
import logo330.expression.ExpressionDivide;
import logo330.expression.ExpressionIdentifier;
import logo330.expression.ExpressionLiteral;
import logo330.expression.ExpressionMultiply;
import logo330.expression.ExpressionSubtract;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
public class OldCompiler extends LogoBaseListener {
public static void main(String[] args) throws FileNotFoundException, IOException {
File f = new File("/Users/johnch/Desktop/lewis.logo");
if (f == null) {
JFileChooser chooser = new JFileChooser();
int ok = chooser.showOpenDialog(null);
if (ok == JFileChooser.APPROVE_OPTION) {
f = chooser.getSelectedFile();
}
}
ANTLRInputStream ais = new ANTLRInputStream(new FileInputStream(f));
LogoLexer lexer = new LogoLexer(ais);
CommonTokenStream tokens = new CommonTokenStream(lexer);
LogoParser parser = new LogoParser(tokens);
ParseTree tree = parser.program();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(new OldCompiler(), tree);
}
@Override
public void exitProgram(ProgramContext ctx) {
Environment env = new Environment();
Block main = blocks.pop();
System.out.println(main.size());
new LogoVirtualMachine(env, main);
}
private Stack<Expression> operands = new Stack<Expression>();
private Stack<Block> blocks = new Stack<Block>();
public void enterBlock(LogoParser.BlockContext context) {
blocks.push(new Block());
}
public void exitIdentifier(IdentifierContext context) {
operands.push(new ExpressionIdentifier(context.ID().getText()));
}
public void exitLiteral(LiteralContext context) {
double value = Double.parseDouble(context.LITERAL().getText());
operands.push(new ExpressionLiteral(value));
}
@Override
public void exitCall(CallContext ctx) {
ArrayList<Expression> actualParameters = new ArrayList<Expression>();
for (int i = 0; i < ctx.expression().size(); ++i) {
actualParameters.add(0, operands.pop());
}
blocks.peek().add(new CommandFunctionCall(ctx.ID().getText(), actualParameters));
}
@Override
public void exitAssignment(AssignmentContext ctx) {
Expression e = operands.pop();
String id = ctx.ID().getText();
blocks.peek().add(new CommandAssignment(id, e));
}
@Override
public void exitBlock(BlockContext ctx) {
}
@Override
public void exitMultiply(MultiplyContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
if (ctx.MULTIPLICATIVE_OPERATOR().getText().equals("*")) {
operands.push(new ExpressionMultiply(a, b));
} else {
operands.push(new ExpressionDivide(a, b));
}
}
@Override
public void exitLog(LogContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandLog(e));
}
@Override
public void exitPen(PenContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandPen(e));
}
@Override
public void exitAdd(AddContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
if (ctx.ADDITIVE_OPERATOR().getText().equals("+")) {
operands.push(new ExpressionAdd(a, b));
} else {
operands.push(new ExpressionSubtract(a, b));
}
}
@Override
public void exitMove(MoveContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandMove(e));
}
@Override
public void exitRotate(RotateContext ctx) {
Expression e = operands.pop();
blocks.peek().add(new CommandRotate(e));
}
@Override
public void exitDefine(DefineContext ctx) {
ArrayList<String> formalParameters = new ArrayList<String>();
for (int i = 1; i < ctx.ID().size(); ++i) {
formalParameters.add(ctx.ID(i).getText());
}
System.out.println(formalParameters);
Block block = blocks.pop();
blocks.peek().add(new CommandFunctionDefine(ctx.name.getText(), formalParameters, block));
}
@Override
public void exitIf(IfContext ctx) {
Block elseBlock = blocks.pop();
Block thenBlock = blocks.pop();
blocks.peek().add(new CommandIf(operands.pop(), thenBlock, elseBlock));
}
@Override
public void exitRepeat(RepeatContext ctx) {
Block block = blocks.pop();
blocks.peek().add(new CommandRepeat(operands.pop(), block));
}
@Override
public void exitPower(PowerContext ctx) {
Expression b = operands.pop();
Expression a = operands.pop();
operands.push(new ExpressionAdd(a, b));
}
}
LogoBaseListener.java
// Generated from Logo.g by ANTLR 4.1
package logo330.antlr;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
/**
* This class provides an empty implementation of {@link LogoListener},
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
public class LogoBaseListener implements LogoListener {
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterLiteral(@NotNull LogoParser.LiteralContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitLiteral(@NotNull LogoParser.LiteralContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterPower(@NotNull LogoParser.PowerContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitPower(@NotNull LogoParser.PowerContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterCall(@NotNull LogoParser.CallContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitCall(@NotNull LogoParser.CallContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterAssignment(@NotNull LogoParser.AssignmentContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitAssignment(@NotNull LogoParser.AssignmentContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterBlock(@NotNull LogoParser.BlockContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitBlock(@NotNull LogoParser.BlockContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterGrouped(@NotNull LogoParser.GroupedContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitGrouped(@NotNull LogoParser.GroupedContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterMultiply(@NotNull LogoParser.MultiplyContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitMultiply(@NotNull LogoParser.MultiplyContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterLog(@NotNull LogoParser.LogContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitLog(@NotNull LogoParser.LogContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterPen(@NotNull LogoParser.PenContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitPen(@NotNull LogoParser.PenContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterProgram(@NotNull LogoParser.ProgramContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitProgram(@NotNull LogoParser.ProgramContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterAdd(@NotNull LogoParser.AddContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitAdd(@NotNull LogoParser.AddContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterMove(@NotNull LogoParser.MoveContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitMove(@NotNull LogoParser.MoveContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterRotate(@NotNull LogoParser.RotateContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitRotate(@NotNull LogoParser.RotateContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterDefine(@NotNull LogoParser.DefineContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitDefine(@NotNull LogoParser.DefineContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterIdentifier(@NotNull LogoParser.IdentifierContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitIdentifier(@NotNull LogoParser.IdentifierContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterIf(@NotNull LogoParser.IfContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitIf(@NotNull LogoParser.IfContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterRepeat(@NotNull LogoParser.RepeatContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitRepeat(@NotNull LogoParser.RepeatContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void enterEveryRule(@NotNull ParserRuleContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void exitEveryRule(@NotNull ParserRuleContext ctx) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void visitTerminal(@NotNull TerminalNode node) { }
/**
* {@inheritDoc}
* <p/>
* The default implementation does nothing.
*/
@Override public void visitErrorNode(@NotNull ErrorNode node) { }
}
LogoLexer.java
// Generated from Logo.g by ANTLR 4.1
package logo330.antlr;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class LogoLexer extends Lexer {
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
TO=1, LOG=2, REPEAT=3, END=4, IF=5, ELSE=6, MOVE=7, ROTATE=8, PEN=9, EQUALS=10,
LEFT_PARENTHESIS=11, RIGHT_PARENTHESIS=12, POWER_OPERATOR=13, MULTIPLICATIVE_OPERATOR=14,
ADDITIVE_OPERATOR=15, LITERAL=16, ID=17, WHITESPACE=18, NEWLINE=19;
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] tokenNames = {
"<INVALID>",
"'to'", "'log'", "'repeat'", "'end'", "'if'", "'else'", "'move'", "'rotate'",
"'pen'", "'='", "'('", "')'", "'^'", "MULTIPLICATIVE_OPERATOR", "ADDITIVE_OPERATOR",
"LITERAL", "ID", "WHITESPACE", "NEWLINE"
};
public static final String[] ruleNames = {
"TO", "LOG", "REPEAT", "END", "IF", "ELSE", "MOVE", "ROTATE", "PEN", "EQUALS",
"LEFT_PARENTHESIS", "RIGHT_PARENTHESIS", "POWER_OPERATOR", "MULTIPLICATIVE_OPERATOR",
"ADDITIVE_OPERATOR", "LITERAL", "ID", "WHITESPACE", "NEWLINE"
};
public LogoLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Logo.g"; }
@Override
public String[] getTokenNames() { return tokenNames; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
@Override
public void action(RuleContext _localctx, int ruleIndex, int actionIndex) {
switch (ruleIndex) {
case 17: WHITESPACE_action((RuleContext)_localctx, actionIndex); break;
}
}
private void WHITESPACE_action(RuleContext _localctx, int actionIndex) {
switch (actionIndex) {
case 0: skip(); break;
}
}
public static final String _serializedATN =
"\3\uacf5\uee8c\u4f5d\u8b0d\u4a45\u78bd\u1b2f\u3378\2\25\u0080\b\1\4\2"+
"\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4"+
"\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22"+
"\t\22\4\23\t\23\4\24\t\24\3\2\3\2\3\2\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4"+
"\3\4\3\4\3\4\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b\3\b\3"+
"\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\n\3\n\3\n\3\n\3\13\3\13\3\f\3"+
"\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\21\5\21a\n\21\3\21\6\21d\n"+
"\21\r\21\16\21e\3\21\3\21\6\21j\n\21\r\21\16\21k\5\21n\n\21\3\22\6\22"+
"q\n\22\r\22\16\22r\3\23\6\23v\n\23\r\23\16\23w\3\23\3\23\3\24\5\24}\n"+
"\24\3\24\3\24\2\25\3\3\1\5\4\1\7\5\1\t\6\1\13\7\1\r\b\1\17\t\1\21\n\1"+
"\23\13\1\25\f\1\27\r\1\31\16\1\33\17\1\35\20\1\37\21\1!\22\1#\23\1%\24"+
"\2\'\25\1\3\2\7\4\2,,\61\61\4\2--//\3\2\62;\3\2c|\4\2\13\13\"\"\u0086"+
"\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+
"\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+
"\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+
"\2\2\2%\3\2\2\2\2\'\3\2\2\2\3)\3\2\2\2\5,\3\2\2\2\7\60\3\2\2\2\t\67\3"+
"\2\2\2\13;\3\2\2\2\r>\3\2\2\2\17C\3\2\2\2\21H\3\2\2\2\23O\3\2\2\2\25S"+
"\3\2\2\2\27U\3\2\2\2\31W\3\2\2\2\33Y\3\2\2\2\35[\3\2\2\2\37]\3\2\2\2!"+
"`\3\2\2\2#p\3\2\2\2%u\3\2\2\2\'|\3\2\2\2)*\7v\2\2*+\7q\2\2+\4\3\2\2\2"+
",-\7n\2\2-.\7q\2\2./\7i\2\2/\6\3\2\2\2\60\61\7t\2\2\61\62\7g\2\2\62\63"+
"\7r\2\2\63\64\7g\2\2\64\65\7c\2\2\65\66\7v\2\2\66\b\3\2\2\2\678\7g\2\2"+
"89\7p\2\29:\7f\2\2:\n\3\2\2\2;<\7k\2\2<=\7h\2\2=\f\3\2\2\2>?\7g\2\2?@"+
"\7n\2\2@A\7u\2\2AB\7g\2\2B\16\3\2\2\2CD\7o\2\2DE\7q\2\2EF\7x\2\2FG\7g"+
"\2\2G\20\3\2\2\2HI\7t\2\2IJ\7q\2\2JK\7v\2\2KL\7c\2\2LM\7v\2\2MN\7g\2\2"+
"N\22\3\2\2\2OP\7r\2\2PQ\7g\2\2QR\7p\2\2R\24\3\2\2\2ST\7?\2\2T\26\3\2\2"+
"\2UV\7*\2\2V\30\3\2\2\2WX\7+\2\2X\32\3\2\2\2YZ\7`\2\2Z\34\3\2\2\2[\\\t"+
"\2\2\2\\\36\3\2\2\2]^\t\3\2\2^ \3\2\2\2_a\7/\2\2`_\3\2\2\2`a\3\2\2\2a"+
"c\3\2\2\2bd\t\4\2\2cb\3\2\2\2de\3\2\2\2ec\3\2\2\2ef\3\2\2\2fm\3\2\2\2"+
"gi\7\60\2\2hj\t\4\2\2ih\3\2\2\2jk\3\2\2\2ki\3\2\2\2kl\3\2\2\2ln\3\2\2"+
"\2mg\3\2\2\2mn\3\2\2\2n\"\3\2\2\2oq\t\5\2\2po\3\2\2\2qr\3\2\2\2rp\3\2"+
"\2\2rs\3\2\2\2s$\3\2\2\2tv\t\6\2\2ut\3\2\2\2vw\3\2\2\2wu\3\2\2\2wx\3\2"+
"\2\2xy\3\2\2\2yz\b\23\2\2z&\3\2\2\2{}\7\17\2\2|{\3\2\2\2|}\3\2\2\2}~\3"+
"\2\2\2~\177\7\f\2\2\177(\3\2\2\2\n\2`ekmrw|";
public static final ATN _ATN =
ATNSimulator.deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}
LogoListener.java
// Generated from Logo.g by ANTLR 4.1
package logo330.antlr;
import org.antlr.v4.runtime.misc.NotNull;
import org.antlr.v4.runtime.tree.ParseTreeListener;
/**
* This interface defines a complete listener for a parse tree produced by
* {@link LogoParser}.
*/
public interface LogoListener extends ParseTreeListener {
/**
* Enter a parse tree produced by {@link LogoParser#Literal}.
* @param ctx the parse tree
*/
void enterLiteral(@NotNull LogoParser.LiteralContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Literal}.
* @param ctx the parse tree
*/
void exitLiteral(@NotNull LogoParser.LiteralContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Power}.
* @param ctx the parse tree
*/
void enterPower(@NotNull LogoParser.PowerContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Power}.
* @param ctx the parse tree
*/
void exitPower(@NotNull LogoParser.PowerContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Call}.
* @param ctx the parse tree
*/
void enterCall(@NotNull LogoParser.CallContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Call}.
* @param ctx the parse tree
*/
void exitCall(@NotNull LogoParser.CallContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Assignment}.
* @param ctx the parse tree
*/
void enterAssignment(@NotNull LogoParser.AssignmentContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Assignment}.
* @param ctx the parse tree
*/
void exitAssignment(@NotNull LogoParser.AssignmentContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#block}.
* @param ctx the parse tree
*/
void enterBlock(@NotNull LogoParser.BlockContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#block}.
* @param ctx the parse tree
*/
void exitBlock(@NotNull LogoParser.BlockContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Grouped}.
* @param ctx the parse tree
*/
void enterGrouped(@NotNull LogoParser.GroupedContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Grouped}.
* @param ctx the parse tree
*/
void exitGrouped(@NotNull LogoParser.GroupedContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Multiply}.
* @param ctx the parse tree
*/
void enterMultiply(@NotNull LogoParser.MultiplyContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Multiply}.
* @param ctx the parse tree
*/
void exitMultiply(@NotNull LogoParser.MultiplyContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Log}.
* @param ctx the parse tree
*/
void enterLog(@NotNull LogoParser.LogContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Log}.
* @param ctx the parse tree
*/
void exitLog(@NotNull LogoParser.LogContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Pen}.
* @param ctx the parse tree
*/
void enterPen(@NotNull LogoParser.PenContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Pen}.
* @param ctx the parse tree
*/
void exitPen(@NotNull LogoParser.PenContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#program}.
* @param ctx the parse tree
*/
void enterProgram(@NotNull LogoParser.ProgramContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#program}.
* @param ctx the parse tree
*/
void exitProgram(@NotNull LogoParser.ProgramContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Add}.
* @param ctx the parse tree
*/
void enterAdd(@NotNull LogoParser.AddContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Add}.
* @param ctx the parse tree
*/
void exitAdd(@NotNull LogoParser.AddContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Move}.
* @param ctx the parse tree
*/
void enterMove(@NotNull LogoParser.MoveContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Move}.
* @param ctx the parse tree
*/
void exitMove(@NotNull LogoParser.MoveContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Rotate}.
* @param ctx the parse tree
*/
void enterRotate(@NotNull LogoParser.RotateContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Rotate}.
* @param ctx the parse tree
*/
void exitRotate(@NotNull LogoParser.RotateContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Define}.
* @param ctx the parse tree
*/
void enterDefine(@NotNull LogoParser.DefineContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Define}.
* @param ctx the parse tree
*/
void exitDefine(@NotNull LogoParser.DefineContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Identifier}.
* @param ctx the parse tree
*/
void enterIdentifier(@NotNull LogoParser.IdentifierContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Identifier}.
* @param ctx the parse tree
*/
void exitIdentifier(@NotNull LogoParser.IdentifierContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#If}.
* @param ctx the parse tree
*/
void enterIf(@NotNull LogoParser.IfContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#If}.
* @param ctx the parse tree
*/
void exitIf(@NotNull LogoParser.IfContext ctx);
/**
* Enter a parse tree produced by {@link LogoParser#Repeat}.
* @param ctx the parse tree
*/
void enterRepeat(@NotNull LogoParser.RepeatContext ctx);
/**
* Exit a parse tree produced by {@link LogoParser#Repeat}.
* @param ctx the parse tree
*/
void exitRepeat(@NotNull LogoParser.RepeatContext ctx);
}
LogoParser.java
// Generated from Logo.g by ANTLR 4.1
package logo330.antlr;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*;
import org.antlr.v4.runtime.tree.*;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class LogoParser extends Parser {
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
TO=1, LOG=2, REPEAT=3, END=4, IF=5, ELSE=6, MOVE=7, ROTATE=8, PEN=9, EQUALS=10,
LEFT_PARENTHESIS=11, RIGHT_PARENTHESIS=12, POWER_OPERATOR=13, MULTIPLICATIVE_OPERATOR=14,
ADDITIVE_OPERATOR=15, LITERAL=16, ID=17, WHITESPACE=18, NEWLINE=19;
public static final String[] tokenNames = {
"<INVALID>", "'to'", "'log'", "'repeat'", "'end'", "'if'", "'else'", "'move'",
"'rotate'", "'pen'", "'='", "'('", "')'", "'^'", "MULTIPLICATIVE_OPERATOR",
"ADDITIVE_OPERATOR", "LITERAL", "ID", "WHITESPACE", "NEWLINE"
};
public static final int
RULE_program = 0, RULE_block = 1, RULE_command = 2, RULE_expression = 3;
public static final String[] ruleNames = {
"program", "block", "command", "expression"
};
@Override
public String getGrammarFileName() { return "Logo.g"; }
@Override
public String[] getTokenNames() { return tokenNames; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public ATN getATN() { return _ATN; }
public LogoParser(TokenStream input) {
super(input);
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
public static class ProgramContext extends ParserRuleContext {
public TerminalNode EOF() { return getToken(LogoParser.EOF, 0); }
public BlockContext block() {
return getRuleContext(BlockContext.class,0);
}
public ProgramContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_program; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterProgram(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitProgram(this);
}
}
public final ProgramContext program() throws RecognitionException {
ProgramContext _localctx = new ProgramContext(_ctx, getState());
enterRule(_localctx, 0, RULE_program);
try {
enterOuterAlt(_localctx, 1);
{
setState(8); block();
setState(9); match(EOF);
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class BlockContext extends ParserRuleContext {
public List<TerminalNode> NEWLINE() { return getTokens(LogoParser.NEWLINE); }
public List<CommandContext> command() {
return getRuleContexts(CommandContext.class);
}
public TerminalNode NEWLINE(int i) {
return getToken(LogoParser.NEWLINE, i);
}
public CommandContext command(int i) {
return getRuleContext(CommandContext.class,i);
}
public BlockContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_block; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterBlock(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitBlock(this);
}
}
public final BlockContext block() throws RecognitionException {
BlockContext _localctx = new BlockContext(_ctx, getState());
enterRule(_localctx, 2, RULE_block);
int _la;
try {
enterOuterAlt(_localctx, 1);
{
setState(16);
_errHandler.sync(this);
_la = _input.LA(1);
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << TO) | (1L << LOG) | (1L << REPEAT) | (1L << IF) | (1L << MOVE) | (1L << ROTATE) | (1L << PEN) | (1L << ID))) != 0)) {
{
{
setState(11); command();
setState(12); match(NEWLINE);
}
}
setState(18);
_errHandler.sync(this);
_la = _input.LA(1);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class CommandContext extends ParserRuleContext {
public CommandContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_command; }
public CommandContext() { }
public void copyFrom(CommandContext ctx) {
super.copyFrom(ctx);
}
}
public static class LogContext extends CommandContext {
public TerminalNode LOG() { return getToken(LogoParser.LOG, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public LogContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterLog(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitLog(this);
}
}
public static class PenContext extends CommandContext {
public TerminalNode PEN() { return getToken(LogoParser.PEN, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public PenContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterPen(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitPen(this);
}
}
public static class CallContext extends CommandContext {
public ExpressionContext expression(int i) {
return getRuleContext(ExpressionContext.class,i);
}
public TerminalNode ID() { return getToken(LogoParser.ID, 0); }
public List<ExpressionContext> expression() {
return getRuleContexts(ExpressionContext.class);
}
public CallContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterCall(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitCall(this);
}
}
public static class AssignmentContext extends CommandContext {
public TerminalNode EQUALS() { return getToken(LogoParser.EQUALS, 0); }
public TerminalNode ID() { return getToken(LogoParser.ID, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public AssignmentContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterAssignment(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitAssignment(this);
}
}
public static class MoveContext extends CommandContext {
public TerminalNode MOVE() { return getToken(LogoParser.MOVE, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public MoveContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterMove(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitMove(this);
}
}
public static class RotateContext extends CommandContext {
public TerminalNode ROTATE() { return getToken(LogoParser.ROTATE, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public RotateContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterRotate(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitRotate(this);
}
}
public static class DefineContext extends CommandContext {
public TerminalNode NEWLINE() { return getToken(LogoParser.NEWLINE, 0); }
public TerminalNode EQUALS() { return getToken(LogoParser.EQUALS, 0); }
public List<TerminalNode> ID() { return getTokens(LogoParser.ID); }
public BlockContext block() {
return getRuleContext(BlockContext.class,0);
}
public TerminalNode TO() { return getToken(LogoParser.TO, 0); }
public TerminalNode END() { return getToken(LogoParser.END, 0); }
public TerminalNode ID(int i) {
return getToken(LogoParser.ID, i);
}
public DefineContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterDefine(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitDefine(this);
}
}
public static class IfContext extends CommandContext {
public List<TerminalNode> NEWLINE() { return getTokens(LogoParser.NEWLINE); }
public TerminalNode IF() { return getToken(LogoParser.IF, 0); }
public TerminalNode NEWLINE(int i) {
return getToken(LogoParser.NEWLINE, i);
}
public TerminalNode ELSE() { return getToken(LogoParser.ELSE, 0); }
public BlockContext block(int i) {
return getRuleContext(BlockContext.class,i);
}
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public List<BlockContext> block() {
return getRuleContexts(BlockContext.class);
}
public TerminalNode END() { return getToken(LogoParser.END, 0); }
public IfContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterIf(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitIf(this);
}
}
public static class RepeatContext extends CommandContext {
public TerminalNode NEWLINE() { return getToken(LogoParser.NEWLINE, 0); }
public TerminalNode REPEAT() { return getToken(LogoParser.REPEAT, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public BlockContext block() {
return getRuleContext(BlockContext.class,0);
}
public TerminalNode END() { return getToken(LogoParser.END, 0); }
public RepeatContext(CommandContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterRepeat(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitRepeat(this);
}
}
public final CommandContext command() throws RecognitionException {
CommandContext _localctx = new CommandContext(_ctx, getState());
enterRule(_localctx, 4, RULE_command);
int _la;
try {
setState(65);
switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) {
case 1:
_localctx = new MoveContext(_localctx);
enterOuterAlt(_localctx, 1);
{
setState(19); match(MOVE);
setState(20); expression(0);
}
break;
case 2:
_localctx = new RotateContext(_localctx);
enterOuterAlt(_localctx, 2);
{
setState(21); match(ROTATE);
setState(22); expression(0);
}
break;
case 3:
_localctx = new RepeatContext(_localctx);
enterOuterAlt(_localctx, 3);
{
setState(23); match(REPEAT);
setState(24); expression(0);
setState(25); match(NEWLINE);
setState(26); block();
setState(27); match(END);
}
break;
case 4:
_localctx = new LogContext(_localctx);
enterOuterAlt(_localctx, 4);
{
setState(29); match(LOG);
setState(30); expression(0);
}
break;
case 5:
_localctx = new IfContext(_localctx);
enterOuterAlt(_localctx, 5);
{
setState(31); match(IF);
setState(32); expression(0);
setState(33); match(NEWLINE);
setState(34); block();
setState(35); match(ELSE);
setState(36); match(NEWLINE);
setState(37); block();
setState(38); match(END);
}
break;
case 6:
_localctx = new DefineContext(_localctx);
enterOuterAlt(_localctx, 6);
{
setState(40); match(TO);
setState(41); match(ID);
setState(45);
_errHandler.sync(this);
_la = _input.LA(1);
while (_la==ID) {
{
{
setState(42); match(ID);
}
}
setState(47);
_errHandler.sync(this);
_la = _input.LA(1);
}
setState(48); match(EQUALS);
setState(49); match(NEWLINE);
setState(50); block();
setState(51); match(END);
}
break;
case 7:
_localctx = new CallContext(_localctx);
enterOuterAlt(_localctx, 7);
{
setState(53); match(ID);
setState(57);
_errHandler.sync(this);
_la = _input.LA(1);
while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LEFT_PARENTHESIS) | (1L << LITERAL) | (1L << ID))) != 0)) {
{
{
setState(54); expression(0);
}
}
setState(59);
_errHandler.sync(this);
_la = _input.LA(1);
}
}
break;
case 8:
_localctx = new AssignmentContext(_localctx);
enterOuterAlt(_localctx, 8);
{
setState(60); match(ID);
setState(61); match(EQUALS);
setState(62); expression(0);
}
break;
case 9:
_localctx = new PenContext(_localctx);
enterOuterAlt(_localctx, 9);
{
setState(63); match(PEN);
setState(64); expression(0);
}
break;
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
exitRule();
}
return _localctx;
}
public static class ExpressionContext extends ParserRuleContext {
public int _p;
public ExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); }
public ExpressionContext(ParserRuleContext parent, int invokingState, int _p) {
super(parent, invokingState);
this._p = _p;
}
@Override public int getRuleIndex() { return RULE_expression; }
public ExpressionContext() { }
public void copyFrom(ExpressionContext ctx) {
super.copyFrom(ctx);
this._p = ctx._p;
}
}
public static class LiteralContext extends ExpressionContext {
public TerminalNode LITERAL() { return getToken(LogoParser.LITERAL, 0); }
public LiteralContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterLiteral(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitLiteral(this);
}
}
public static class PowerContext extends ExpressionContext {
public TerminalNode POWER_OPERATOR() { return getToken(LogoParser.POWER_OPERATOR, 0); }
public ExpressionContext expression(int i) {
return getRuleContext(ExpressionContext.class,i);
}
public List<ExpressionContext> expression() {
return getRuleContexts(ExpressionContext.class);
}
public PowerContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterPower(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitPower(this);
}
}
public static class AddContext extends ExpressionContext {
public ExpressionContext expression(int i) {
return getRuleContext(ExpressionContext.class,i);
}
public List<ExpressionContext> expression() {
return getRuleContexts(ExpressionContext.class);
}
public TerminalNode ADDITIVE_OPERATOR() { return getToken(LogoParser.ADDITIVE_OPERATOR, 0); }
public AddContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterAdd(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitAdd(this);
}
}
public static class IdentifierContext extends ExpressionContext {
public TerminalNode ID() { return getToken(LogoParser.ID, 0); }
public IdentifierContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterIdentifier(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitIdentifier(this);
}
}
public static class GroupedContext extends ExpressionContext {
public TerminalNode LEFT_PARENTHESIS() { return getToken(LogoParser.LEFT_PARENTHESIS, 0); }
public TerminalNode RIGHT_PARENTHESIS() { return getToken(LogoParser.RIGHT_PARENTHESIS, 0); }
public ExpressionContext expression() {
return getRuleContext(ExpressionContext.class,0);
}
public GroupedContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterGrouped(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitGrouped(this);
}
}
public static class MultiplyContext extends ExpressionContext {
public ExpressionContext expression(int i) {
return getRuleContext(ExpressionContext.class,i);
}
public TerminalNode MULTIPLICATIVE_OPERATOR() { return getToken(LogoParser.MULTIPLICATIVE_OPERATOR, 0); }
public List<ExpressionContext> expression() {
return getRuleContexts(ExpressionContext.class);
}
public MultiplyContext(ExpressionContext ctx) { copyFrom(ctx); }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).enterMultiply(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof LogoListener ) ((LogoListener)listener).exitMultiply(this);
}
}
public final ExpressionContext expression(int _p) throws RecognitionException {
ParserRuleContext _parentctx = _ctx;
int _parentState = getState();
ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState, _p);
ExpressionContext _prevctx = _localctx;
int _startState = 6;
enterRecursionRule(_localctx, RULE_expression);
try {
int _alt;
enterOuterAlt(_localctx, 1);
{
setState(74);
switch (_input.LA(1)) {
case LEFT_PARENTHESIS:
{
_localctx = new GroupedContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(68); match(LEFT_PARENTHESIS);
setState(69); expression(0);
setState(70); match(RIGHT_PARENTHESIS);
}
break;
case LITERAL:
{
_localctx = new LiteralContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(72); match(LITERAL);
}
break;
case ID:
{
_localctx = new IdentifierContext(_localctx);
_ctx = _localctx;
_prevctx = _localctx;
setState(73); match(ID);
}
break;
default:
throw new NoViableAltException(this);
}
_ctx.stop = _input.LT(-1);
setState(87);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,6,_ctx);
while ( _alt!=2 && _alt!=-1 ) {
if ( _alt==1 ) {
if ( _parseListeners!=null ) triggerExitRuleEvent();
_prevctx = _localctx;
{
setState(85);
switch ( getInterpreter().adaptivePredict(_input,5,_ctx) ) {
case 1:
{
_localctx = new PowerContext(new ExpressionContext(_parentctx, _parentState, _p));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
setState(76);
if (!(5 >= _localctx._p)) throw new FailedPredicateException(this, "5 >= $_p");
setState(77); match(POWER_OPERATOR);
setState(78); expression(6);
}
break;
case 2:
{
_localctx = new MultiplyContext(new ExpressionContext(_parentctx, _parentState, _p));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
setState(79);
if (!(4 >= _localctx._p)) throw new FailedPredicateException(this, "4 >= $_p");
setState(80); match(MULTIPLICATIVE_OPERATOR);
setState(81); expression(5);
}
break;
case 3:
{
_localctx = new AddContext(new ExpressionContext(_parentctx, _parentState, _p));
pushNewRecursionContext(_localctx, _startState, RULE_expression);
setState(82);
if (!(3 >= _localctx._p)) throw new FailedPredicateException(this, "3 >= $_p");
setState(83); match(ADDITIVE_OPERATOR);
setState(84); expression(4);
}
break;
}
}
}
setState(89);
_errHandler.sync(this);
_alt = getInterpreter().adaptivePredict(_input,6,_ctx);
}
}
}
catch (RecognitionException re) {
_localctx.exception = re;
_errHandler.reportError(this, re);
_errHandler.recover(this, re);
}
finally {
unrollRecursionContexts(_parentctx);
}
return _localctx;
}
public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
switch (ruleIndex) {
case 3: return expression_sempred((ExpressionContext)_localctx, predIndex);
}
return true;
}
private boolean expression_sempred(ExpressionContext _localctx, int predIndex) {
switch (predIndex) {
case 0: return 5 >= _localctx._p;
case 1: return 4 >= _localctx._p;
case 2: return 3 >= _localctx._p;
}
return true;
}
public static final String _serializedATN =
"\3\uacf5\uee8c\u4f5d\u8b0d\u4a45\u78bd\u1b2f\u3378\3\25]\4\2\t\2\4\3\t"+
"\3\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\3\3\3\3\3\7\3\21\n\3\f\3\16\3\24\13\3"+
"\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+
"\4\3\4\3\4\3\4\3\4\3\4\3\4\7\4.\n\4\f\4\16\4\61\13\4\3\4\3\4\3\4\3\4\3"+
"\4\3\4\3\4\7\4:\n\4\f\4\16\4=\13\4\3\4\3\4\3\4\3\4\3\4\5\4D\n\4\3\5\3"+
"\5\3\5\3\5\3\5\3\5\3\5\5\5M\n\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\7"+
"\5X\n\5\f\5\16\5[\13\5\3\5\2\6\2\4\6\b\2\2h\2\n\3\2\2\2\4\22\3\2\2\2\6"+
"C\3\2\2\2\bL\3\2\2\2\n\13\5\4\3\2\13\f\7\2\2\3\f\3\3\2\2\2\r\16\5\6\4"+
"\2\16\17\7\25\2\2\17\21\3\2\2\2\20\r\3\2\2\2\21\24\3\2\2\2\22\20\3\2\2"+
"\2\22\23\3\2\2\2\23\5\3\2\2\2\24\22\3\2\2\2\25\26\7\t\2\2\26D\5\b\5\2"+
"\27\30\7\n\2\2\30D\5\b\5\2\31\32\7\5\2\2\32\33\5\b\5\2\33\34\7\25\2\2"+
"\34\35\5\4\3\2\35\36\7\6\2\2\36D\3\2\2\2\37 \7\4\2\2 D\5\b\5\2!\"\7\7"+
"\2\2\"#\5\b\5\2#$\7\25\2\2$%\5\4\3\2%&\7\b\2\2&\'\7\25\2\2\'(\5\4\3\2"+
"()\7\6\2\2)D\3\2\2\2*+\7\3\2\2+/\7\23\2\2,.\7\23\2\2-,\3\2\2\2.\61\3\2"+
"\2\2/-\3\2\2\2/\60\3\2\2\2\60\62\3\2\2\2\61/\3\2\2\2\62\63\7\f\2\2\63"+
"\64\7\25\2\2\64\65\5\4\3\2\65\66\7\6\2\2\66D\3\2\2\2\67;\7\23\2\28:\5"+
"\b\5\298\3\2\2\2:=\3\2\2\2;9\3\2\2\2;<\3\2\2\2<D\3\2\2\2=;\3\2\2\2>?\7"+
"\23\2\2?@\7\f\2\2@D\5\b\5\2AB\7\13\2\2BD\5\b\5\2C\25\3\2\2\2C\27\3\2\2"+
"\2C\31\3\2\2\2C\37\3\2\2\2C!\3\2\2\2C*\3\2\2\2C\67\3\2\2\2C>\3\2\2\2C"+
"A\3\2\2\2D\7\3\2\2\2EF\b\5\1\2FG\7\r\2\2GH\5\b\5\2HI\7\16\2\2IM\3\2\2"+
"\2JM\7\22\2\2KM\7\23\2\2LE\3\2\2\2LJ\3\2\2\2LK\3\2\2\2MY\3\2\2\2NO\6\5"+
"\2\3OP\7\17\2\2PX\5\b\5\2QR\6\5\3\3RS\7\20\2\2SX\5\b\5\2TU\6\5\4\3UV\7"+
"\21\2\2VX\5\b\5\2WN\3\2\2\2WQ\3\2\2\2WT\3\2\2\2X[\3\2\2\2YW\3\2\2\2YZ"+
"\3\2\2\2Z\t\3\2\2\2[Y\3\2\2\2\t\22/;CLWY";
public static final ATN _ATN =
ATNSimulator.deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}
Command.java
package logo330.command;
import logo330.Environment;
public abstract class Command {
protected abstract void reallyExecute(Environment env);
public void execute(Environment env) {
reallyExecute(env);
if (env.listener != null) {
env.listener.onPostCommand();
}
}
}
CommandAssignment.java
package logo330.command;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandAssignment extends Command {
private String id;
private Expression expr;
public CommandAssignment(String id, Expression expr) {
this.id = id;
this.expr = expr;
}
@Override
protected void reallyExecute(Environment env) {
env.locals.put(id, expr.evaluate(env));
}
}
CommandFunctionCall.java
package logo330.command;
import java.util.ArrayList;
import java.util.HashMap;
import logo330.Environment;
import logo330.Function;
import logo330.expression.Expression;
public class CommandFunctionCall extends Command {
private String id;
private ArrayList<Expression> actualParameters;
public CommandFunctionCall(String id, ArrayList<Expression> actualParameters) {
this.id = id;
this.actualParameters = actualParameters;
}
@Override
protected void reallyExecute(Environment env) {
Function f = env.functions.get(id);
HashMap<String, Double> outerLocals = env.locals;
HashMap<String, Double> innerLocals = new HashMap<String, Double>();
for (int i = 0; i < actualParameters.size(); ++i) {
innerLocals.put(f.getFormalParameters().get(i), actualParameters.get(i).evaluate(env));
}
env.locals = innerLocals;
f.getBody().execute(env);
env.locals = outerLocals;
}
}
CommandFunctionDefine.java
package logo330.command;
import java.util.ArrayList;
import logo330.Block;
import logo330.Environment;
import logo330.Function;
public class CommandFunctionDefine extends Command {
private Function f;
public CommandFunctionDefine(String id, ArrayList<String> formalParameters, Block body) {
f = new Function(id, formalParameters, body);
}
@Override
protected void reallyExecute(Environment env) {
env.functions.put(f.getID(), f);
}
}
CommandIf.java
package logo330.command;
import logo330.Block;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandIf extends Command {
private Expression expr;
private Block thenBlock;
private Block elseBlock;
public CommandIf(Expression expr, Block thenBlock, Block elseBlock) {
this.expr = expr;
this.thenBlock = thenBlock;
this.elseBlock = elseBlock;
}
@Override
protected void reallyExecute(Environment env) {
if (Math.abs(expr.evaluate(env)) > 1.0e-3f) {
thenBlock.execute(env);
} else {
elseBlock.execute(env);
}
}
}
CommandListener.java
package logo330.command;
public interface CommandListener {
public void onPostCommand();
}
CommandLog.java
package logo330.command;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandLog extends Command {
private Expression expr;
public CommandLog(Expression expr) {
this.expr = expr;
}
@Override
protected void reallyExecute(Environment env) {
System.out.println(expr.evaluate(env));
}
}
CommandMove.java
package logo330.command;
import java.awt.geom.Line2D;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandMove extends Command {
private Expression expr;
public CommandMove(Expression expr) {
this.expr = expr;
}
@Override
protected void reallyExecute(Environment env) {
double newX = env.x + Math.cos(env.theta) * expr.evaluate(env);
double newY = env.y + Math.sin(env.theta) * expr.evaluate(env);
if (env.isDrawing) {
synchronized (env.segments) {
env.segments.add(new Line2D.Double(env.x, env.y, newX, newY));
}
}
env.x = newX;
env.y = newY;
}
}
CommandPen.java
package logo330.command;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandPen extends Command {
private Expression expr;
public CommandPen(Expression expr) {
this.expr = expr;
}
@Override
protected void reallyExecute(Environment env) {
env.isDrawing = Math.abs(expr.evaluate(env)) < 1.0e-3f;
}
}
CommandRepeat.java
package logo330.command;
import logo330.Block;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandRepeat extends Command {
private Expression expr;
private Block block;
public CommandRepeat(Expression expr, Block block) {
this.expr = expr;
this.block = block;
}
@Override
protected void reallyExecute(Environment env) {
int n = (int) expr.evaluate(env);
for (int i = 0; i < n; ++i) {
block.execute(env);
}
}
}
CommandRotate.java
package logo330.command;
import logo330.Environment;
import logo330.expression.Expression;
public class CommandRotate extends Command {
private Expression expr;
public CommandRotate(Expression expr) {
this.expr = expr;
}
@Override
protected void reallyExecute(Environment env) {
env.theta += Math.toRadians(expr.evaluate(env));
}
}
Expression.java
package logo330.expression;
import logo330.Environment;
public abstract class Expression {
public abstract double evaluate(Environment env);
}
ExpressionAdd.java
package logo330.expression;
import logo330.Environment;
public class ExpressionAdd extends Expression {
private Expression l;
private Expression r;
public ExpressionAdd(Expression l, Expression r) {
this.l = l;
this.r = r;
}
public double evaluate(Environment env) {
return l.evaluate(env) + r.evaluate(env);
}
}
ExpressionDivide.java
package logo330.expression;
import logo330.Environment;
public class ExpressionDivide extends Expression {
private Expression l;
private Expression r;
public ExpressionDivide(Expression l, Expression r) {
this.l = l;
this.r = r;
}
public double evaluate(Environment env) {
return l.evaluate(env) / r.evaluate(env);
}
}
ExpressionIdentifier.java
package logo330.expression;
import java.util.NoSuchElementException;
import logo330.Environment;
public class ExpressionIdentifier extends Expression {
private String id;
public ExpressionIdentifier(String id) {
this.id = id;
}
public double evaluate(Environment env) {
if (env.locals.containsKey(id)) {
return env.locals.get(id);
} else {
throw new NoSuchElementException(id);
}
}
}
ExpressionLiteral.java
package logo330.expression;
import logo330.Environment;
public class ExpressionLiteral extends Expression {
private double value;
public ExpressionLiteral(double value) {
this.value = value;
}
public double evaluate(Environment env) {
return value;
}
}
ExpressionMultiply.java
package logo330.expression;
import logo330.Environment;
public class ExpressionMultiply extends Expression {
private Expression l;
private Expression r;
public ExpressionMultiply(Expression l, Expression r) {
this.l = l;
this.r = r;
}
public double evaluate(Environment env) {
return l.evaluate(env) * r.evaluate(env);
}
}
ExpressionPower.java
package logo330.expression;
import logo330.Environment;
public class ExpressionPower extends Expression {
private Expression l;
private Expression r;
public ExpressionPower(Expression l, Expression r) {
this.l = l;
this.r = r;
}
public double evaluate(Environment env) {
return Math.pow(l.evaluate(env), r.evaluate(env));
}
}
ExpressionSubtract.java
package logo330.expression;
import logo330.Environment;
public class ExpressionSubtract extends Expression {
private Expression l;
private Expression r;
public ExpressionSubtract(Expression l, Expression r) {
this.l = l;
this.r = r;
}
public double evaluate(Environment env) {
return l.evaluate(env) - r.evaluate(env);
}
}
Haiku
Without rules, I cheat
Without discipline, I slave
Without
Without discipline, I slave
Without
exception
s, I fly through the error on wings of deviance