options { LOOKAHEAD=1; IGNORE_CASE=true; } PARSER_BEGIN(Q2) class Move { int direction; int steps; Move(int d, int s) { direction=d; steps=s; } } public class Q2 { // At all times we want to know where the robot is, and in // which direction it's facing: static int xpos=0, ypos=0; static final int NORTH=0, EAST=1, SOUTH=2, WEST=3; static int orient=NORTH; static void doAction(Move m) { orient = (orient+m.direction)%4; switch(orient) { case NORTH: ypos+=m.steps; break; case EAST: xpos+=m.steps; break; case SOUTH: ypos-=m.steps; break; case WEST: xpos-=m.steps; break; } } /*** Main function - just call parser and print result ***/ public static void main(String args[]) throws ParseException { Q2 parser = new Q2(System.in); try { parser.command(); System.out.println("You are at position ("+xpos+","+ypos+")"); double dist = Math.sqrt(((xpos*xpos)+(ypos*ypos))); System.out.println("Thus the distance travelled is " + dist); } catch (ParseException x) { System.out.println("Exiting."); throw x; } } } PARSER_END(Q2) /*** Ignoring whitespace ***/ SKIP : { " " | "\t" } /******************/ /***** TOKENS *****/ /******************/ TOKEN : /* Number = sequence of digits */ { < NUM : ()+ > | < #DIGIT : ["0" - "9"] > } TOKEN : /* Keywords NB - this must be placed before defn of identifiers */ { < THEN : "then" > | < AFTER : "after" > | < FORWARD : "forward" > | < LEFT : "left" > | < RIGHT : "right" > | < BACK : "back" > } TOKEN : /* Punctuation */ { < LBR : "(" > | < RBR : ")" > } /*************************/ /***** GRAMMAR RULES *****/ /*************************/ /***** Program *****/ void command() : {} { thens() ( | "\n" | "\r") } void thens() : {} { afters() ( afters() )* } void afters() : { Move b; } { b=basic() [ afters() ] { if (b!=null) doAction(b); } } Move basic() : { int d; Token n; } { d=direction() n= { return new Move(d,Integer.parseInt(n.image)); } | thens() { return null; } } int direction() : {} { { return 0; } | { return 1; } | { return 2; } | { return 3; } }