public void toDot(String filename) {
		System.out.println("Writing " + filename);
		BufferedWriter w = null;
		try {
			FileWriter fstream = new FileWriter(filename);
			w = new BufferedWriter(fstream);
		
			w.write("digraph G {\n");
			
			// nodes
			for (PDAState s : states) {
				String id = Util.dotId(s);
				if (id.length() > 200) {
					id = Util.dotId(s.id);
				}
				w.write("" + s.id + " [label=" + id + (s.rejects ? ", color=red" : "") + ", shape=box];\n");
	
				// shift edges
				for (Entry<Symbol, PDAState> e2 : s.shifts.entrySet()) {
					w.write("" + s.id + " -> " + e2.getValue().id + " [label=" + Util.dotId(e2.getKey()) + "];\n");
				}
				
				// goto edges
				for (Entry<R, PDAState> e2 : s.gotos.entrySet()) {
					w.write("" + s.id + " -> " + e2.getValue().id + " [label=" + "R" + s.id /*Util.dotId(e2.getKey())*/ + "];\n");
				}
				
				if (s.rejectState != null) {
					w.write("" + s.id + " -> " + s.rejectState.id + " [color=red];\n");
				}
			}
						
			w.write("}\n");
			
		} catch (Exception e) {
			System.err.println("Error: " + e.getMessage());
		} finally {
			if (w != null) {
				try {
					w.close();
				} catch (IOException e) { }
			}
		}
	}