/* * An interpreter for the ETA programming language. * See http://www.miketaylor.org.uk/tech/eta/doc/index.html * for more information on ETA. */ import java.io.*; public class eta implements Runnable { private char[] prog; private int[] pcByLine; private Stack s; private int pc = -1; public eta (String file) throws FileNotFoundException, IOException { BufferedReader in = new BufferedReader(new FileReader(file)); try { StringBuffer sb = new StringBuffer(); Stack pcByLineStack = new Stack(); pcByLineStack.push(-1); // to fill slot 0 String line; while ((line = in.readLine()) != null) { pcByLineStack.push(sb.length()); for (int i = 0; i < line.length(); i++) { char c = Character.toLowerCase(line.charAt(i)); switch (c) { case 'e': case 't': case 'a': case 'o': case 'i': case 'n': case 's': case 'h': sb.append(c); } } } prog = sb.toString().toCharArray(); pcByLine = pcByLineStack.toArray(); } finally { in.close(); } } public int currentLine() { if (pc < 0) return 0; int low = 1; int high = pcByLine.length-1; while (low <= high) { int mid = (low+high)/2; if (pc < pcByLine[mid-1]) { high = mid-1; } else if (pc >= pcByLine[mid]) { low = mid+1; } else { return mid-1; } } return pcByLine.length-1; } public void e() { int b = s.pop(); int a = s.pop(); s.push(a/b); s.push(a%b); } public void t() { int addr = s.pop(); int cond = s.pop(); if (cond != 0) { pc = pcByLine[addr]-1; } } public void a() { s.push(currentLine()+1); } public void o() { System.out.print((char)s.pop()); // unclear spec - what if not 0-255 } public void i() { try { s.push(System.in.read()); } catch (IOException ex) { System.err.println(ex.toString()); } } public void n() { int start = pc+1; while (prog[++pc] != 'e'); String str = new String(prog, start, pc-start); int i = etautils.parseEtaInt(str); s.push(i); } public void s() { s.push(-s.pop()+s.pop()); // to get correct order } public void h() { int n = s.pop(); s.push(n > 0 ? s.remove(n) : s.get(-n)); } public void execute(char c) { switch (c) { case 'e': e(); return; case 't': t(); return; case 'a': a(); return; case 'o': o(); return; case 'i': i(); return; case 'n': n(); return; case 's': s(); return; case 'h': h(); return; } } public void run() { s = new Stack(); for (pc = 0; pc >= 0 && pc < prog.length; pc++) { //System.out.print(prog[pc]); //dumpStack(); execute(prog[pc]); //try { Thread.sleep(100); } catch (InterruptedException ex){} } } private void printArray (int[] arr) { System.out.print('['); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]); if (i < arr.length-1) System.out.print(','); } System.out.println(']'); } /* private void dumpStack() { int[] arr = s.toArray(); System.out.print("l: " + currentLine() + " pc: "+pc+" i: "+prog[pc]+" s: "); printArray(arr); } */ public static void main(String[] args) throws IOException { if (args.length == 0) { System.err.println("Usage: eta file"); System.exit(1); } eta inter = new eta(args[0]); inter.run(); } /* private static class LStack { private Node top = null; public LStack () {} public void push (int i) { top = new Node(i, top); } public int pop () { Node old_top = top; top = old_top.next; return old_top.value; } public int get(int off) { Node n = top; while (off-- > 0) { n = n.next; } return n.value; } public int remove(int off) { if (off == 0) { Node r = top; top = r.next; return r.value; } else { Node n = top; while (off-- > 1) { n = n.next; } // n is the node just over the one to remove Node r = n.next; n.next = r.next; return r.value; } } private static class Node { protected int value; protected Node next; public Node (int value, Node next) { this.value = value; this.next = next; } } } */ private static class Stack { private int[] arr = new int[1024]; private int p = -1; public Stack() {} public void push(int i) { arr[++p] = i; if (p >= arr.length-1) { int[] newarr = new int[arr.length*2]; System.arraycopy(arr, 0, newarr, 0, arr.length); arr = newarr; } } public int pop() { return arr[p--]; } public int get(int off) { return arr[p-off]; } public int remove(int off) { int pos = p-off; int r = arr[pos]; System.arraycopy(arr, pos+1, arr, pos, off); p--; return r; } public int[] toArray() { int[] r = new int[p+1]; System.arraycopy(arr, 0, r, 0, p+1); return r; } } }