Java : [id:lethevert:20060801:p3]を作った
Javaで作ってみた。
parse関数内に、Parserクラスを作って、関数内関数のように扱っている。
public class Main { public static void main (String[] args) { String input = "(begin\n" + " (print (concat Hell \"o W\" \"orld!\"))\n" + " (print \"1+2*3*4 = \" (+ 1 (* 2 3 4)))\n" + " ((concat pri nt) ok))\n"; evalArgs(parse(input.toCharArray())); } static class Cons { Cons (Object a, Object d) { car = a; cdr = d;} Object car; Object cdr; } static Object car (Object o) { return ((Cons) o).car; } static Object cdr (Object o) { return ((Cons) o).cdr; } static Object last (Object o) { while (cdr(o)!=null) { o = cdr(o);} return o; } static Cons parse (final char[] in) { final int l = in.length; class Parser { int i = 0; StringBuffer buf = new StringBuffer(); Cons getSymbol() { if (buf.length()==0) { return null; }else{ Cons c = new Cons(buf.toString(), null); buf.delete(0,buf.length()); return c; } } Cons parse() { while (i<l) { char c = in[i++]; switch (c) { case '(':{ Cons c0 = getSymbol(); Cons c1 = new Cons(parse(), parse()); if (c0==null){ return c1; }else{ c0.cdr = c1; return c0; } } case ')': return getSymbol(); case '"': { Cons c0 = getSymbol(); Cons c1 = parseStr(); c1.cdr = parse(); if (c0==null){ return c1; }else{ c0.cdr = c1; return c0; } } case ' ': case '\t': case '\n': case '\r':{ Cons c0 = getSymbol(); if (c0==null){ continue; }else{ c0.cdr = parse(); return c0; } } default: buf.append(c); continue; } } return null; } Cons parseStr() { while (i<l) { char c = in[i++]; switch (c) { case '\\': buf.append(c); buf.append(in[i++]); continue; case '"': return getSymbol(); default: buf.append(c); continue; } } throw new RuntimeException(); } } return new Parser().parse(); } static Cons evalArgs (Cons c) { if (c==null){ return null; }else{ Cons r; Cons r1 = r = new Cons(eval(c.car), null); while ((c=(Cons)c.cdr)!=null) { r1 = (Cons) (r1.cdr = new Cons(eval(c.car), null)); } return r; } } static Object eval (Object o) { if (o==null){ return null; }else if (o instanceof Cons){ Cons c = (Cons) o; c = evalArgs(c); if (c.car.equals("begin")){ return car(last(c.cdr)); }else if (c.car.equals("print")){ while ((c=(Cons)c.cdr)!=null){ System.out.print(c.car.toString()); } System.out.println(); return "ok"; }else if (c.car.equals("concat")){ StringBuffer buf = new StringBuffer(); while ((c=(Cons)c.cdr)!=null){ buf.append(c.car.toString()); } return buf.toString(); }else if (c.car.equals("+")){ int sum = 0; while ((c=(Cons)c.cdr)!=null){ sum += Integer.parseInt(c.car.toString()); } return Integer.toString(sum); }else if (c.car.equals("*")){ int prod = 1; while ((c=(Cons)c.cdr)!=null){ prod *= Integer.parseInt(c.car.toString()); } return Integer.toString(prod); }else{ throw new RuntimeException(c.car.toString()); } }else{ return o; } } }