/*
 * Copyright 2014 Yuichiro Moriguchi
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.morilib.deculture.parser;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import net.morilib.automata.lr.Associativity;
import net.morilib.automata.lr.Terminal;
import net.morilib.deculture.misc.CharacterTerminal;
import net.morilib.deculture.misc.ConstantTerminal;

/**
 */
public  class DecultureDefinition   {

	static class TokenException extends RuntimeException {
	}

	static abstract class Engine {
		abstract int step(java.io.Reader __rd, int c) throws java.io.IOException;
		abstract boolean accepted();
		abstract int execaction(int c);
		abstract boolean isend();
		abstract int recover(Exception e);
		abstract int deadState();
		abstract int stateSize();
		abstract int finallyState();
	}
	private static final int NINA_BEGIN = -2;
	private static final int NINA_EOF = -1;
	private static final int NINA_ACCEPT = -8;
	private static final int NINA_FAIL = -9;
	private static final int NINA_HALT_ACCEPT = -91;
	private static final int NINA_HALT_REJECT = -72;
	private static final int NINA_YIELD = -85;
	private static final int NINA_STACKLEN = 72;
	static final int INITIAL = 0;

	private int STATE;
	private int[] __sts = new int[NINA_STACKLEN];
	private Engine[] __stk = new Engine[NINA_STACKLEN];
	private Object[][] __stv = new Object[NINA_STACKLEN][];
	private int __slen = 0;
	private int unread = -1;

	Object _;
	java.util.List<Object> _l;
	Object yieldObject;
	java.io.Reader befstream = null;
	Throwable exception;

	void _initlist() {
		_l = new java.util.ArrayList<Object>();
	}

	void _addlist(Object x) {
		_l.add(x);
	}

	private int __lookahead_state;
	private int __lookahead_mark = -1;
	private int[] __lookahead = null;
	private int __lookahead_ptr = -1;
	private int[] __lookaheadw = null;
	private int __lookaheadw_ptr = -1;
	private boolean __lookahead_ok = true;

	int _read1(java.io.Reader stream) throws java.io.IOException {
		int c;

		c = stream.read();
		return c < 0 ? NINA_EOF : c;
	}

	private int _read(java.io.Reader rd) throws java.io.IOException {
		int c;

		while(true) {
			if(unread != -1) {

				c = unread;
				unread = -1;
				__logprint("Read unread: ", c);
			} else if(__lookahead_ptr >= 0) {
				if(__lookahead_ptr < __lookahead.length) {
					c = __lookahead[__lookahead_ptr++];
				} else {
					__lookahead = null;
					__lookahead_ptr = -1;
					c = _read(rd);
				}
				__logprint("Read Lookahead: ", c);
			} else if((c = _read1(rd)) != -1) {
				__logprint("Read: ", c);
			} else {
				__logprint("Read end-of-file");
			}
			return c;
		}
	}

	void UNGET(int c) {
		unread = c;
		__logprint("Set unread: ", c);
	}

	void __sleep(int m) {
		try {
			Thread.sleep(m);
		} catch(InterruptedException e) {
			throw new RuntimeException(e);
		}
	}

	private void __logprint(String s, int c) {
	}

	private void __logopen() {
	}

	private void __logprint(String s) {
	}

	private void __logclose() {
	}

	private void __puttrace() {
	}

	void LOOKAHEAD(int c) {
		int[] a;

		if(__lookaheadw == null) {
			__lookahead_state = STATE;
			__lookaheadw = new int[72];
			__lookaheadw_ptr = 0;
			__lookaheadw[__lookaheadw_ptr++] = c;
		} else if(__lookaheadw_ptr < __lookaheadw.length) {
			__lookaheadw[__lookaheadw_ptr++] = c;
		} else {
			a = new int[__lookaheadw.length * 2];
			System.arraycopy(__lookaheadw, 0, a, 0,
					__lookaheadw.length);
			__lookaheadw = a;
			__lookaheadw[__lookaheadw_ptr++] = c;
		}
	}

	private void __copy_lookahead(int p) {
		int[] a;

		if(__lookahead == null) {
			a = new int[__lookaheadw_ptr];
		} else if(__lookaheadw_ptr < __lookahead.length) {
			a = __lookahead;
		} else {
			a = new int[__lookaheadw_ptr];
		}
		System.arraycopy(__lookaheadw, 0, a, 0, __lookaheadw_ptr);
		__lookahead = a;
		__lookahead_ptr = p;
		__lookaheadw = null;
		__lookaheadw_ptr = -1;
	}

	void LOOKAHEAD_COMMIT() {
		if(__lookahead_mark < 0) {
			__lookaheadw = null;
			__lookaheadw_ptr = -1;
		} else {
			__copy_lookahead(__lookahead_mark);
		}
		__lookahead_mark = -1;
		__logprint("Commit Lookahead");
	}

	void LOOKAHEAD_RB() {
		__copy_lookahead(0);
		STATE = __lookahead_state;
		__lookahead_ok = false;
		__lookahead_mark = -1;
		__logprint("Rollback Lookahead");
	}

	void LOOKAHEAD_MARK() {
		__lookahead_mark = __lookaheadw_ptr;
	}


	private int decultureDefinition_step(java.io.Reader __rd, int  $c)  throws java.io.IOException {
		boolean __l__ = __lookahead_ok;

		__lookahead_ok = true;
		switch(STATE) {
		case 0:
			if($c == '\n') {
				STATE = 0;
				return 1;
			} else if($c == '%') {
				STATE = 1;
				return 1;
			} else if($c >= 0) {
				STATE = 2;
				return 1;
			}
			return 0;
		case 2:
			if($c == '\n') {
				STATE = 0;
				return 1;
			} else if($c >= 0) {
				STATE = 2;
				return 1;
			}
			return 0;
		case 1:
			if(__l__ && $c == 'l') {
				LOOKAHEAD($c);
				STATE = 3;
				return 1;
			} else if(__l__ && $c == 'n') {
				LOOKAHEAD($c);
				STATE = 4;
				return 1;
			} else if(__l__ && $c == 'r') {
				LOOKAHEAD($c);
				STATE = 5;
				return 1;
			} else if($c == 's') {
				STATE = 6;
				return 1;
			} else if($c == 't') {
				STATE = 7;
				return 1;
			} else if($c == '{') {
				STATE = 8;
				return 1;
			}
			return 0;
		case 8:
			if($c == '%') {
				STATE = 9;
				return 1;
			} else if($c >= 0) {
				STATE = 10;
				return 1;
			}
			return 0;
		case 10:
			if($c == '%') {
				STATE = 9;
				return 1;
			} else if($c >= 0) {
				STATE = 10;
				return 1;
			}
			return 0;
		case 9:
			if($c == '}') {
				STATE = 0;
				return 1;
			} else if($c >= 0) {
				_d('%');
				STATE = 10;
				return 1;
			}
			return 0;
		case 7:
			if($c == 'o') {
				STATE = 11;
				return 1;
			} else if($c == 'y') {
				STATE = 12;
				return 1;
			}
			return 0;
		case 12:
			if($c == 'p') {
				STATE = 13;
				return 1;
			}
			return 0;
		case 13:
			if($c == 'e') {
				STATE = 14;
				return 1;
			}
			return 0;
		case 14:
			if($c >= 9 && $c <= 13) {
				STATE = 15;
				return 1;
			} else if($c == ' ') {
				STATE = 15;
				return 1;
			} else if($c == '<') {
				STATE = 16;
				return 1;
			}
			return 0;
		case 16:
			if($c >= 0) {
				STATE = 17;
				return 1;
			}
			return 0;
		case 17:
			if($c == '<') {
				STATE = 18;
				return 1;
			} else if($c == '>') {
				STATE = 19;
				return 1;
			} else if($c >= 0) {
				STATE = 17;
				return 1;
			}
			return 0;
		case 19:
			if($c >= 9 && $c <= 13) {
				STATE = 19;
				return 1;
			} else if($c == ' ') {
				STATE = 19;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 20;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 20;
				return 1;
			}
			return 0;
		case 20:
			if($c >= '0' && $c <= '9') {
				STATE = 20;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 20;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 20;
				return 1;
			} else if($c >= 0) {
				UNGET($c);
				STATE = 21;
				return 1;
			}
			return 0;
		case 21:
			if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 0) {
				STATE = 21;
				return 1;
			}
			return 0;
		case 18:
			if($c == '>') {
				STATE = 17;
				return 1;
			} else if($c >= 0) {
				STATE = 18;
				return 1;
			}
			return 0;
		case 15:
			if($c >= 9 && $c <= 13) {
				STATE = 15;
				return 1;
			} else if($c == ' ') {
				STATE = 15;
				return 1;
			} else if($c == '<') {
				STATE = 16;
				return 1;
			}
			return 0;
		case 11:
			if($c == 'k') {
				STATE = 22;
				return 1;
			}
			return 0;
		case 22:
			if($c == 'e') {
				STATE = 23;
				return 1;
			}
			return 0;
		case 23:
			if($c == 'n') {
				STATE = 24;
				return 1;
			}
			return 0;
		case 24:
			if($c >= 9 && $c <= 13) {
				STATE = 25;
				return 1;
			} else if($c == ' ') {
				STATE = 25;
				return 1;
			} else if($c == '<') {
				STATE = 26;
				return 1;
			}
			return 0;
		case 26:
			if($c == '"') {
				STATE = 27;
				return 1;
			} else if($c >= 0) {
				STATE = 28;
				return 1;
			}
			return 0;
		case 28:
			if($c == '"') {
				STATE = 27;
				return 1;
			} else if($c == '<') {
				STATE = 29;
				return 1;
			} else if($c == '>') {
				STATE = 30;
				return 1;
			} else if($c >= 0) {
				STATE = 28;
				return 1;
			}
			return 0;
		case 30:
			if($c >= 9 && $c <= 13) {
				STATE = 30;
				return 1;
			} else if($c == ' ') {
				STATE = 30;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 31;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 31;
				return 1;
			}
			return 0;
		case 31:
			if($c >= '0' && $c <= '9') {
				STATE = 31;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 31;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 31;
				return 1;
			} else if($c >= 0) {
				UNGET($c);
				STATE = 32;
				return 1;
			}
			return 0;
		case 32:
			if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 0) {
				STATE = 32;
				return 1;
			}
			return 0;
		case 29:
			if($c == '>') {
				STATE = 28;
				return 1;
			} else if($c >= 0) {
				STATE = 29;
				return 1;
			}
			return 0;
		case 27:
			if($c == '"') {
				STATE = 28;
				return 1;
			} else if($c >= 0) {
				STATE = 27;
				return 1;
			}
			return 0;
		case 25:
			if($c >= 9 && $c <= 13) {
				STATE = 25;
				return 1;
			} else if($c == ' ') {
				STATE = 25;
				return 1;
			} else if($c == '<') {
				STATE = 26;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 31;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 31;
				return 1;
			}
			return 0;
		case 6:
			if($c == 't') {
				STATE = 33;
				return 1;
			}
			return 0;
		case 33:
			if($c == 'a') {
				STATE = 34;
				return 1;
			}
			return 0;
		case 34:
			if($c == 'r') {
				STATE = 35;
				return 1;
			}
			return 0;
		case 35:
			if($c == 't') {
				STATE = 36;
				return 1;
			}
			return 0;
		case 36:
			if($c >= 9 && $c <= 13) {
				STATE = 37;
				return 1;
			} else if($c == ' ') {
				STATE = 37;
				return 1;
			}
			return 0;
		case 37:
			if($c >= 9 && $c <= 13) {
				STATE = 37;
				return 1;
			} else if($c == ' ') {
				STATE = 37;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 38;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 38;
				return 1;
			}
			return 0;
		case 38:
			if($c >= 9 && $c <= 13) {
				STATE = 39;
				return 1;
			} else if($c == ' ') {
				STATE = 39;
				return 1;
			} else if($c >= '0' && $c <= '9') {
				STATE = 38;
				return 1;
			} else if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 38;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 38;
				return 1;
			}
			return 0;
		case 39:
			if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 0) {
				STATE = 39;
				return 1;
			}
			return 0;
		case 5:
			if(__l__ && $c == 'i') {
				LOOKAHEAD($c);
				STATE = 40;
				return 1;
			}
			return 0;
		case 40:
			if(__l__ && $c == 'g') {
				LOOKAHEAD($c);
				STATE = 41;
				return 1;
			}
			return 0;
		case 41:
			if(__l__ && $c == 'h') {
				LOOKAHEAD($c);
				STATE = 42;
				return 1;
			}
			return 0;
		case 42:
			if($c == 't') {
				LOOKAHEAD_COMMIT();
				STATE = 43;
				return 1;
			}
			return 0;
		case 43:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			}
			return 0;
		case 44:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			} else if($c == '\'') {
				STATE = 45;
				return 1;
			} else if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 46;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 46;
				return 1;
			}
			return 0;
		case 46:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			} else if($c >= '0' && $c <= '9') {
				STATE = 46;
				return 1;
			} else if($c == ';') {
				STATE = 47;
				return 1;
			} else if($c >= 'A' && $c <= 'Z') {
				STATE = 46;
				return 1;
			} else if($c >= 'a' && $c <= 'z') {
				STATE = 46;
				return 1;
			}
			return 0;
		case 47:
			if($c >= 0) {
				UNGET($c);
				STATE = 2;
				return 1;
			}
			return 0;
		case 45:
			if($c == '\\') {
				STATE = 48;
				return 1;
			} else if($c >= 0) {
				STATE = 49;
				return 1;
			}
			return 0;
		case 49:
			if($c == '\'') {
				STATE = 50;
				return 1;
			}
			return 0;
		case 50:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			} else if($c == ';') {
				STATE = 47;
				return 1;
			}
			return 0;
		case 48:
			if($c >= 0) {
				STATE = 49;
				return 1;
			}
			return 0;
		case 4:
			if(__l__ && $c == 'o') {
				LOOKAHEAD($c);
				STATE = 51;
				return 1;
			}
			return 0;
		case 51:
			if(__l__ && $c == 'n') {
				LOOKAHEAD($c);
				STATE = 52;
				return 1;
			}
			return 0;
		case 52:
			if(__l__ && $c == 'a') {
				LOOKAHEAD($c);
				STATE = 53;
				return 1;
			}
			return 0;
		case 53:
			if(__l__ && $c == 's') {
				LOOKAHEAD($c);
				STATE = 54;
				return 1;
			}
			return 0;
		case 54:
			if(__l__ && $c == 's') {
				LOOKAHEAD($c);
				STATE = 55;
				return 1;
			}
			return 0;
		case 55:
			if(__l__ && $c == 'o') {
				LOOKAHEAD($c);
				STATE = 56;
				return 1;
			}
			return 0;
		case 56:
			if($c == 'c') {
				LOOKAHEAD_COMMIT();
				STATE = 57;
				return 1;
			}
			return 0;
		case 57:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			}
			return 0;
		case 3:
			if(__l__ && $c == 'e') {
				LOOKAHEAD($c);
				STATE = 58;
				return 1;
			}
			return 0;
		case 58:
			if(__l__ && $c == 'f') {
				LOOKAHEAD($c);
				STATE = 59;
				return 1;
			} else if(__l__ && $c == 'x') {
				LOOKAHEAD($c);
				STATE = 60;
				return 1;
			}
			return 0;
		case 60:
			if(__l__ && $c == 'e') {
				LOOKAHEAD($c);
				STATE = 61;
				return 1;
			}
			return 0;
		case 61:
			if($c == 'r') {
				LOOKAHEAD_COMMIT();
				STATE = 62;
				return 1;
			}
			return 0;
		case 62:
			if($c >= 9 && $c <= 13) {
				STATE = 63;
				return 1;
			} else if($c == ' ') {
				STATE = 63;
				return 1;
			}
			return 0;
		case 63:
			if($c >= 9 && $c <= 13) {
				STATE = 63;
				return 1;
			} else if($c == ' ') {
				STATE = 63;
				return 1;
			} else if($c >= 0) {
				STATE = 64;
				return 1;
			}
			return 0;
		case 64:
			if($c >= 0 && $c <= 8) {
				STATE = 64;
				return 1;
			} else if($c >= 14 && $c <= 31) {
				STATE = 64;
				return 1;
			} else if($c >= '!' && $c <= ':') {
				STATE = 64;
				return 1;
			} else if($c >= '<' && $c <= 2147483647) {
				STATE = 64;
				return 1;
			} else if($c >= 0) {
				UNGET($c);
				STATE = 65;
				return 1;
			}
			return 0;
		case 65:
			if($c == ';') {
				STATE = 2;
				return 1;
			} else if($c >= 0) {
				STATE = 65;
				return 1;
			}
			return 0;
		case 59:
			if($c == 't') {
				LOOKAHEAD_COMMIT();
				STATE = 66;
				return 1;
			}
			return 0;
		case 66:
			if($c >= 9 && $c <= 13) {
				STATE = 44;
				return 1;
			} else if($c == ' ') {
				STATE = 44;
				return 1;
			}
			return 0;
		}
		return 0;
	}

	private boolean decultureDefinition_accepted() {
		return (STATE == 0 ||
				STATE == 2);
	}

	int decultureDefinition_execaction(int  $c) {
		switch(STATE) {
		case 2:
			break;
		case 19:
			_tp();
			break;
		case 53:
			break;
		case 22:
			break;
		case 33:
			break;
		case 34:
			break;
		case 42:
			break;
		case 24:
			_ib();
			break;
		case 50:
			break;
		case 64:
			_l($c);
			break;
		case 66:
			_il();
			break;
		case 43:
			_ir();
			break;
		case 12:
			break;
		case 30:
			_tp();
			break;
		case 13:
			break;
		case 56:
			break;
		case 62:
			break;
		case 28:
			_b($c);
			break;
		case 49:
			ch = $c;
			break;
		case 26:
			break;
		case 44:
			_pa();
			break;
		case 10:
			_d($c);
			break;
		case 40:
			break;
		case 65:
			break;
		case 29:
			_b($c);
			break;
		case 5:
			break;
		case 38:
			_s($c);
			break;
		case 7:
			break;
		case 45:
			break;
		case 57:
			_ix();
			break;
		case 9:
			break;
		case 54:
			break;
		case 51:
			break;
		case 60:
			break;
		case 0:
			break;
		case 39:
			break;
		case 32:
			_pt();
			break;
		case 11:
			break;
		case 47:
			_pe();
			break;
		case 55:
			break;
		case 23:
			break;
		case 59:
			break;
		case 48:
			break;
		case 8:
			break;
		case 18:
			_b($c);
			break;
		case 31:
			_b($c);
			break;
		case 41:
			break;
		case 16:
			break;
		case 52:
			break;
		case 14:
			_ib();
			break;
		case 36:
			break;
		case 37:
			break;
		case 58:
			break;
		case 27:
			_b($c);
			break;
		case 46:
			_b($c);
			break;
		case 4:
			break;
		case 17:
			_b($c);
			break;
		case 25:
			break;
		case 6:
			break;
		case 1:
			break;
		case 15:
			break;
		case 20:
			_b($c);
			break;
		case 61:
			break;
		case 63:
			break;
		case 35:
			break;
		case 3:
			break;
		case 21:
			_pn();
			break;
		}
		return 1;
	}

	boolean decultureDefinition_isend() {
		return false;
	}

	private final Engine ENGINE_decultureDefinition = new Engine() {

		int step(java.io.Reader __rd, int c) throws java.io.IOException {
			return decultureDefinition_step(__rd, c);
		}

		boolean accepted() {
			return decultureDefinition_accepted();
		}

		int execaction(int c) {
			return decultureDefinition_execaction(c);
		}

		boolean isend() {
			return decultureDefinition_isend();
		}

		int recover(Exception e) {
			return -1;
		}

		int deadState() {
			return -1;
		}

		int stateSize() {
			return 67;
		}

		int finallyState() {
			return -1;
		}

		public String toString() {
			return "decultureDefinition";
		}

	};

	void __stkpush(int st, Engine en) {
		Object[][] c;
		Engine[] b;
		int[] a;

		if(__slen >= __sts.length) {
			a = new int[__sts.length * 2];
			b = new Engine[__stk.length * 2];
			c = new Object[__stk.length * 2][];
			System.arraycopy(__sts, 0, a, 0, __sts.length);
			System.arraycopy(__stk, 0, b, 0, __stk.length);
			System.arraycopy(__stv, 0, c, 0, __stv.length);
			__sts = a;
			__stk = b;
			__stv = c;
		}
		__sts[__slen] = st;
		__stk[__slen] = en;
		__stv[__slen++] = new Object[en.stateSize()];
	}

	private int _parse(java.io.Reader rd, int x, Boolean rt,
			boolean skip, int[] st) throws java.io.IOException {
		boolean b = false, p = skip;
		int c = x;
		Engine en;
		int a;

		b = __stk[__slen - 1].accepted();
		if(rd == null) {
			throw new RuntimeException("can not recurse");
		} else if(rt.booleanValue()) {
			switch(__stk[__slen - 1].execaction(NINA_BEGIN)) {
			case NINA_ACCEPT:
				__logprint("accept " + __stk[__slen - 1]);
				st[0] = NINA_ACCEPT;  return -1;
			case NINA_FAIL:
				__logprint("match failed: begin");
				__puttrace();
				st[0] = NINA_FAIL;  return -1;
			case NINA_HALT_ACCEPT:
				__logprint("machine halted: begin");
				st[0] = NINA_HALT_ACCEPT;  return -1;
			case NINA_HALT_REJECT:
				__logprint("machine halted: begin");
				st[0] = NINA_HALT_REJECT;  return -1;
			case NINA_YIELD:
				__logprint("machine yielded: ", c);
				st[0] = NINA_YIELD;  return -1;
			}
		}

		try {
			do {
				en = __stk[__slen - 1];
				if(p) {
					p = false;
				} else if((a = en.step(rd, c)) > 0) {
					__logprint("transit to state " + STATE + ": ", c);
					b = en.accepted();
					switch(en.execaction(c)) {
					case NINA_ACCEPT:
						__logprint("accept " + __stk[__slen - 1]);
						UNGET(c);
						st[0] = NINA_ACCEPT;  return -1;
					case NINA_FAIL:
						__logprint("match failed: ", c);
						__puttrace();
						UNGET(c);
						st[0] = NINA_FAIL;  return -1;
					case NINA_HALT_ACCEPT:
						__logprint("machine halted: ", c);
						st[0] = NINA_HALT_ACCEPT;  return -1;
					case NINA_HALT_REJECT:
						__logprint("machine halted: ", c);
						st[0] = NINA_HALT_REJECT;  return -1;
					case NINA_YIELD:
						__logprint("machine yielded: ", c);
						st[0] = NINA_YIELD;  return -1;
					}
				} else if(a < 0) {
					__logprint("entering " + __stk[__slen - 1]);
					return c;
				} else if(b) {
					__logprint("accept " + __stk[__slen - 1]);
					UNGET(c);
					st[0] = NINA_ACCEPT;  return -1;
				} else if(__lookaheadw_ptr >= 0) {
					__logprint("match failed: try lookahead: ", c);
					LOOKAHEAD(c);
					LOOKAHEAD_RB();
					b = en.accepted();
				} else if(c == -1) {
					if(!b)  throw new TokenException();
					st[0] = NINA_ACCEPT;  return -1;
				} else {
					__logprint("match failed: ", c);
					__puttrace();
					UNGET(c);
					st[0] = NINA_FAIL;  return -1;
				}
				c = _read(rd);
			} while(true);
		} catch(RuntimeException e) {
			UNGET(c);
			throw e;
		}
	}

	private Boolean execfinally() {
		int a, b;

		if((a = __stk[__slen - 1].finallyState()) >= 0) {
			b = STATE;  STATE = a;
			switch(__stk[__slen - 1].execaction(NINA_BEGIN)) {
			case NINA_HALT_ACCEPT:
				__slen = 0;
				return Boolean.TRUE;
			case NINA_HALT_REJECT:
				__slen = 0;
				return Boolean.FALSE;
			}
			STATE = b;
		}
		return null;
	}

	private int getdeadstate() {
		return __stk[__slen - 1].deadState();
	}

	private int getrecover(Exception e) {
		return __stk[__slen - 1].recover(e);
	}

	 boolean parse(java.io.Reader rd, Engine entry) throws java.io.IOException {
		Boolean b = Boolean.FALSE;
		int[] a = new int[1];
		boolean skip = true;
		int c = 0;

		__logopen();
		try {
			if(__slen == 0) {
				b = Boolean.TRUE;
				__stkpush(0, entry);
			}

			ot: while(true) {
				try {
					if((c = _parse(rd, c, b, skip, a)) != -1) {
						skip = false;
					} else if(a[0] == NINA_FAIL) {
						while((STATE = getdeadstate()) < 0) {
							if((b = execfinally()) != null)  break ot;
							if(__slen-- <= 1) {
								throw new TokenException();
							}
						}
						skip = true;
					} else if(a[0] == NINA_HALT_ACCEPT) {
						if((b = execfinally()) != null)  break;
						__slen = 0;
						b = Boolean.TRUE;  break;
					} else if(a[0] == NINA_HALT_REJECT) {
						if((b = execfinally()) != null)  break;
						__slen = 0;
						b = Boolean.FALSE;  break;
					} else if(a[0] == NINA_YIELD) {
						return false;
					} else if(__slen > 1) {
						if((b = execfinally()) != null)  break;
						STATE = __sts[--__slen];
						skip = true;
					} else {
						if((b = execfinally()) != null)  break;
						b = new Boolean(__stk[--__slen].accepted());
						break;
					}
				} catch(RuntimeException e) {
					exception = e;
					if(__slen <= 0)  throw e;
					while((STATE = getrecover(e)) < 0) {
						if((b = execfinally()) != null)  return b;
						if(__slen-- <= 1)  throw e;
					}
				}
				b = Boolean.TRUE;
			}
			if(!b.booleanValue())  throw new TokenException();
			return b.booleanValue();
		} finally {
			__logclose();
		}
	}

	public boolean parse(java.io.Reader rd) throws java.io.IOException {
		return parse(rd, ENGINE_decultureDefinition);
	}

	 static boolean parseAll(java.io.Reader rd) throws java.io.IOException {
		DecultureDefinition o = new DecultureDefinition();

		return o.parse(rd);
	}

	 void setStream(java.io.Reader rd) {
		if(befstream != null) {
			throw new IllegalStateException();
		}
		yieldObject = befstream = rd;
	}

	 Object parseNext() throws java.io.IOException {
		Object o;

		if(befstream == null) {
			throw new IllegalStateException();
		} else if(yieldObject == null) {
			return null;
		} else if(parse(befstream, ENGINE_decultureDefinition)) {
			if(yieldObject == null)  throw new NullPointerException();
			o = yieldObject;  yieldObject = null;
			return o;
		} else {
			if(yieldObject == null)  throw new NullPointerException();
			return yieldObject;
		}
	}

	 boolean parse(java.io.InputStream rd) throws java.io.IOException {
		return parse(new java.io.InputStreamReader(rd));
	}

	 static boolean parseAll(
			java.io.InputStream rd) throws java.io.IOException {
		return parseAll(new java.io.InputStreamReader(rd));
	}

private Map<String, String> tokens = new HashMap<String, String>();
private Map<Terminal, Integer> priority = new HashMap<Terminal, Integer>();
private Map<Terminal, Associativity> associative = new HashMap<Terminal, Associativity>();
private Map<String, String> nttypes = new HashMap<String, String>();
private StringBuffer def = new StringBuffer();
private StringBuffer str = new StringBuffer();
private StringBuffer lex = new StringBuffer();
private StringBuffer buf;
private String tp;
private int ch, prior = 0;
private Associativity assoc;
private Map<Object, Integer> tpri;

public String getDefinition() {
	return def.toString();
}

public String getStartSymbolName() {
	return str.toString();
}

public String getLexerName() {
	return lex.toString();
}

public boolean isToken(String s) {
	return tokens.containsKey(s);
}

public Map<String, String> getTokens() {
	return Collections.unmodifiableMap(tokens);
}

public String getType(String s) {
	String t;

	if(!tokens.containsKey(s)) {
		return null;
	} else if((t = tokens.get(s)) != null) {
		return t;
	} else {
		return "Object";
	}
}

public String getNonterminalType(String s) {
	String t;

	if(!nttypes.containsKey(s)) {
		return null;
	} else if((t = nttypes.get(s)) != null) {
		return t;
	} else {
		return "Object";
	}
}

public Map<Terminal, Integer> getPriority() {
	return Collections.unmodifiableMap(priority);
}

public Map<Terminal, Associativity> getAssociativity() {
	return Collections.unmodifiableMap(associative);
}

private void _d(int c) {
	if(c >= 0)  def.appendCodePoint(c);
}

private void _s(int c) {
	if(c >= 0)  str.appendCodePoint(c);
}

private void _b(int c) {
	if(c >= 0)  buf.appendCodePoint(c);
}

private void _l(int c) {
	if(c >= 0)  lex.appendCodePoint(c);
}

private void _tp() {
	if(buf.length() > 0)  tp = buf.toString();
	buf = new StringBuffer();
}

private void _pt() {
	if(buf != null) {
		tokens.put(buf.toString(), tp);
		buf = null;
	}
}

private void _pn() {
	if(buf != null) {
		nttypes.put(buf.toString(), tp);
		buf = null;
	}
}

private void _ib() {
	buf = new StringBuffer();
	tp  = null;
	ch  = -1;
}

private void _il() {
	tpri = new HashMap<Object, Integer>();
	buf = new StringBuffer();
	ch  = -1;
	assoc = Associativity.LEFT;
}

private void _ir() {
	tpri = new HashMap<Object, Integer>();
	buf = new StringBuffer();
	ch  = -1;
	assoc = Associativity.RIGHT;
}

private void _ix() {
	tpri = new HashMap<Object, Integer>();
	buf = new StringBuffer();
	ch  = -1;
	assoc = Associativity.NONASSOC;
}

private void _pa() {
	if(ch >= 0) {
		tpri.put(Character.valueOf((char)ch), prior);
		ch  = -1;
	} else if(buf.length() > 0) {
		tpri.put(buf.toString(), prior);
		buf = new StringBuffer();
	}
}

private void _pe() {
	Terminal o;

	_pa();
	for(Map.Entry<Object, Integer> t : tpri.entrySet()) {
		if(t.getKey() instanceof Character) {
			o = new CharacterTerminal(((Character)t.getKey()).charValue());
		} else {
			o = new ConstantTerminal(t.getKey().toString());
		}
		priority.put(o, t.getValue());
		associative.put(o, assoc);
	}
	prior++;
}

}
