CS 330 Lecture 11 – Basecalc Interpreter Cont’d
Agenda
- what ?s
- defining an interpreter
- add callbacks to interpreter
- internode communication
- variables
TODO
- See post Git Syncing + Permissions Issues on Thingies on Piazza to fix some problems you are likely to encounter.
- Get your homework (at least the first two problems) pushed to Bitbucket before Friday. If you can’t see your code on Bitbucket’s site, neither can I. Also, a reminder: I am not available for your last-minute emergencies. Please spread your emergencies out into the past two weeks. Overcoming problems with the thingies and git and so on are just as much part of completing this homework as writing regular expressions.
Think About This
- What’s the difference between an interpreter and a compiler? Where does Java fit into this scheme? How about C?
- Most interpreted languages have an
eval
function that accepts a string and executes it. Why don’t we see this in C or Java?
Code
Basecalc.g
grammar Basecalc;
line
: expr # DecimalOutput
| expr CAST DIGITS # BaseOutput
;
expr
: LEFT_PARENTHESIS expr RIGHT_PARENTHESIS # Grouped
| NOT expr # Negate
| expr POWER expr # Power
| expr MULTIPLICATIVE_OPERATOR expr # Multiply
| expr ADDITIVE_OPERATOR expr # Add
| expr SHIFT expr # Shift
| expr AND expr # And
| expr XOR expr # Xor
| expr OR expr # Or
| IDENTIFIER ASSIGNMENT expr # Assignment
| DIGITS # Literal
| n=DIGITS LESS base=DIGITS GREATER # LiteralWithBase
| IDENTIFIER # Identifier
;
LEFT_PARENTHESIS: '(';
RIGHT_PARENTHESIS: ')';
POWER: '^^';
MULTIPLICATIVE_OPERATOR: [*/%];
ADDITIVE_OPERATOR: [-+];
NOT: '~';
SHIFT: '<<' | '>>';
AND: '&';
XOR: '^';
OR: '|';
ASSIGNMENT: ':=';
CAST: '->';
LESS: '<';
GREATER: '>';
IDENTIFIER: '$' [a-z]+ [a-z_]*;
DIGITS: [0-9a-zA-Z]+;
WHITESPACE: [ \n\r\t]+ -> skip;
Repl.java
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.CommonTokenStream;
import java.util.Scanner;
public class Repl {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Interpreter interpreter = new Interpreter();
System.out.print("> ");
while (in.hasNextLine()) {
String line = in.nextLine();
ANTLRInputStream ais = new ANTLRInputStream(line);
BasecalcLexer lexer = new BasecalcLexer(ais);
CommonTokenStream tokens = new CommonTokenStream(lexer);
BasecalcParser parser = new BasecalcParser(tokens);
ParseTree tree = parser.line();
ParseTreeWalker walker = new ParseTreeWalker();
walker.walk(interpreter, tree);
System.out.print("> ");
}
}
}
Interpreter.java
import java.util.HashMap;
import java.util.Stack;
public class Interpreter extends BasecalcBaseListener {
private Stack<Integer> operands;
private HashMap<String, Integer> variables;
public Interpreter() {
operands = new Stack<>();
variables = new HashMap<>();
}
@Override
public void exitDecimalOutput(BasecalcParser.DecimalOutputContext ctx) {
System.out.println(operands.pop());
}
@Override
public void exitBaseOutput(BasecalcParser.BaseOutputContext ctx) {
String baseAsString = ctx.DIGITS().getText();
int base = Integer.parseInt(baseAsString);
System.out.println(Integer.toString(operands.pop(), base) + "<" + base + ">");
}
@Override
public void exitLiteral(BasecalcParser.LiteralContext ctx) {
String digitsAsString = ctx.DIGITS().getText();
int digits = Integer.parseInt(digitsAsString);
operands.push(digits);
}
@Override
public void exitLiteralWithBase(BasecalcParser.LiteralWithBaseContext ctx) {
String digitsAsString = ctx.n.getText();
String baseAsString = ctx.base.getText();
int base = Integer.parseInt(baseAsString);
int digits = Integer.parseInt(digitsAsString, base);
operands.push(digits);
}
@Override
public void exitAdd(BasecalcParser.AddContext ctx) {
int b = operands.pop();
int a = operands.pop();
if (ctx.ADDITIVE_OPERATOR().getText().equals("+")) {
operands.push(a + b);
} else {
operands.push(a - b);
}
}
@Override
public void exitPower(BasecalcParser.PowerContext ctx) {
int b = operands.pop();
int a = operands.pop();
operands.push((int) Math.pow(a, b));
}
@Override
public void exitNegate(BasecalcParser.NegateContext ctx) {
int a = operands.pop();
operands.push(~a);
}
@Override
public void exitXor(BasecalcParser.XorContext ctx) {
int b = operands.pop();
int a = operands.pop();
operands.push(a ^ b);
}
@Override
public void exitMultiply(BasecalcParser.MultiplyContext ctx) {
int b = operands.pop();
int a = operands.pop();
if (ctx.MULTIPLICATIVE_OPERATOR().getText().equals("*")) {
operands.push(a * b);
} else if (ctx.MULTIPLICATIVE_OPERATOR().getText().equals("/")) {
operands.push(a / b);
} else {
operands.push(a % b);
}
}
@Override
public void exitAnd(BasecalcParser.AndContext ctx) {
int b = operands.pop();
int a = operands.pop();
operands.push(a & b);
}
@Override
public void exitOr(BasecalcParser.OrContext ctx) {
int b = operands.pop();
int a = operands.pop();
operands.push(a | b);
}
@Override
public void exitShift(BasecalcParser.ShiftContext ctx) {
int b = operands.pop();
int a = operands.pop();
if (ctx.SHIFT().getText().equals("<<")) {
operands.push(a << b);
} else {
operands.push(a >> b);
}
}
@Override
public void exitAssignment(BasecalcParser.AssignmentContext ctx) {
variables.put(ctx.IDENTIFIER().getText(), operands.peek());
}
@Override
public void exitIdentifier(BasecalcParser.IdentifierContext ctx) {
System.out.println(ctx.IDENTIFIER().getText());
operands.push(variables.get(ctx.IDENTIFIER().getText()));
}
}
Haiku
how I feel about recursion
Left hand, hold the nail
Right hand, you swing the hammer
Brain says, “What’s my job?”
Left hand, hold the nail
Right hand, you swing the hammer
Brain says, “What’s my job?”