teaching machines

CS 330 Lecture 11 – Basecalc Interpreter Cont’d

February 18, 2015 by . Filed under cs330, lectures, spring 2015.

Agenda

TODO

Think About This

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?”