//VirtualMachine
import gi.*;
/*\semantics*/import java.util.*;
/*\off*/
class VirtualMachine extends SLR1_Grammar {

	VirtualMachine() throws Exception {
		put("LITERAL", expression("[[:digit:]]+"));
		put("IDENTIFIER", expression("[[:alpha:]][[:alnum:]]*"));
		put("BRANCH", expression("b(lt|eq|gt|ge|ne|le)"));
		put("SPACE", expression("[[:space:]]+"));

		// /*\semantics*/semantic specification/*\off*/
//VirtualMachine.InstrList
/*\semantics*/		final Map<String,ParseTree> labels = new HashMap<String,ParseTree>();

//VirtualMachine.Program
/*\semantics*/		Semantics run = new Semantics() {

			String operation(ParseTree ic) {return (String)ic.child[0].value;}
			String operand(ParseTree ic) {return (String)ic.child[1].value;}
			ParseTree next(ParseTree ic) {return (ParseTree)ic.value;}

			public void f(ParseTree t, int l) {
				Stack<Integer> runtime = new Stack<Integer>();
				Map<String,Integer> memory = new HashMap<String,Integer>();
				int comparator = 0;

				for (ParseTree ic = (ParseTree)t.child[l-1].value; ic != null;) {
					String operation = operation(ic);

					// instruction execution
//VirtualMachine.Program.instruction
/*\semantics*/					if (operation.equals("lc")) {
						runtime.push(new Integer(operand(ic)));
					}
					else if (operation.equals("load")) {
						runtime.push(memory.get(operand(ic)));
					}
					else if (operation.equals("store")) {
						memory.put(operand(ic), runtime.pop());
					}
					else if (operation.equals("goto")) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("comp")) {
						int right = runtime.pop(), left = runtime.pop();
						comparator =
							(left < right) ? 0x4 :
							(left == right) ? 0x2 : 0x1;
					}
					else if (operation.equals("blt") && (comparator & 0x4) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("beq") && (comparator & 0x2) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("bgt") && (comparator & 0x1) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("bge") && (comparator & 0x3) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("bne") && (comparator & 0x5) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("ble") && (comparator & 0x6) > 0) {
						ic = labels.get(operand(ic)); continue;
					}
					else if (operation.equals("add")) {
						int right = runtime.pop(), left = runtime.pop();
						runtime.push(left + right);
					}
					else if (operation.equals("mult")) {
						int right = runtime.pop(), left = runtime.pop();
						runtime.push(left * right);
					}/*\off*/
//VirtualMachine.Program

					ic = next(ic);
				}
				System.out.println("runtime = " + runtime);
				System.out.println("memory = " + memory);
				System.out.println("comparator = " + comparator);
			}
		};
/*\off*/		put("Program", new Object[][] {
			{"InstrList"/*\semantics*/, run/*\off*/},
		});
//VirtualMachine.InstrList
		Semantics assemble = new Semantics() {
			public void f(ParseTree t, int l) {
				t.child[l-2].value = t.child[l-1].value;
				t.value = t.child[l-2];
			}
		};
		Semantics label = new Semantics() {
			public void f(ParseTree t, int l) {
				labels.put((String)t.child[l-3].value, (ParseTree)t.child[l-1].value);
				t.value = t.child[l-1].value;
			}
		};
/*\off*/		put("InstrList", new Object[][] {
			{},
			{"Instr", "InstrList"/*\semantics*/, assemble/*\off*/},
			{"IDENTIFIER", ":", "InstrList"/*\semantics*/, label/*\off*/},
		});
		put("Instr", new Object[][] {
			{"lc", "LITERAL"},
			{"load", "IDENTIFIER"},
			{"store", "IDENTIFIER"},
			{"goto", "IDENTIFIER"},
			{"comp"},
			{"BRANCH", "IDENTIFIER"},
			{"add"},
			{"mult"},
		});
//VirtualMachine
	}

	public static void main(String[] arguments) throws Exception {
		new VirtualMachine().interpret(arguments);
	}
}
