--- /dev/null
+package $package$;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+
+$imports$
+public abstract class $class$ {
+ public static final boolean TRACE = false;
+
+ private static final int INITIAL_CAPACITY = 16;
+ private static final int STATE_COUNT = $stateCount$;
+ private static final int TERMINAL_COUNT = $terminalCount$;
+ private static final int NONTERMINAL_COUNT = $nonterminalCount$;
+ private static final int PRODUCT_COUNT = $productCount$;
+
+ private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];
+ private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];
+ private static final short[] ACTION_TABLE = new short[$actionTableLength$];
+ private static final int[] ERROR_TABLE = new int[$errorTableLength$];
+ private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];
+ private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];
+ private static final short[] GOTO_TABLE = new short[$gotoTableLength$];
+ private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];
+
+ private static final short STATE_MASK = (short)0x0fff;
+ private static final short REDUCE_MASK = (short)0x8000;
+ private static final short POP_MASK = (short)0x4000;
+ private static final short PUSH_MASK = (short)0x2000;
+ private static final short ERROR_ACTION = (short)0xffff;
+ private static final short ACCEPT_ACTION = (short)0xfffe;
+
+ public static final String[] TERMINAL_NAMES = new String[] {
+$terminalNames$
+ };
+
+ public static final String[] NONTERMINAL_NAMES = new String[] {
+$nonterminalNames$
+ };
+
+ static {
+ try {
+ DataInputStream input = new DataInputStream($class$.class.getResourceAsStream("$class$.dat"));
+ for(int i=0;i<ACTION_ROW_ID.length;++i)
+ ACTION_ROW_ID[i] = input.readInt();
+ for(int i=0;i<ACTION_COLUMN_ID.length;++i)
+ ACTION_COLUMN_ID[i] = input.readInt();
+ for(int i=0;i<ACTION_TABLE.length;++i)
+ ACTION_TABLE[i] = input.readShort();
+ for(int i=0;i<ERROR_TABLE.length;++i)
+ ERROR_TABLE[i] = input.readInt();
+ for(int i=0;i<GOTO_ROW_ID.length;++i)
+ GOTO_ROW_ID[i] = input.readInt();
+ for(int i=0;i<GOTO_COLUMN_ID.length;++i)
+ GOTO_COLUMN_ID[i] = input.readInt();
+ for(int i=0;i<GOTO_TABLE.length;++i)
+ GOTO_TABLE[i] = input.readShort();
+ for(int i=0;i<PRODUCT_LHS.length;++i)
+ PRODUCT_LHS[i] = input.readInt();
+ input.close();
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static short getAction(int state, int symbol) {
+ int id = TERMINAL_COUNT*state + symbol;
+ if( ((ERROR_TABLE[id>>5] >> (id&31))&1) != 0 )
+ return ERROR_ACTION;
+ return ACTION_TABLE[ACTION_ROW_ID[state] + ACTION_COLUMN_ID[symbol]];
+ }
+
+ private static short getGoto(int state, int symbol) {
+ return GOTO_TABLE[GOTO_ROW_ID[state] + GOTO_COLUMN_ID[symbol]];
+ }
+
+ protected abstract $Token$ nextToken();
+
+ private $Symbol$[] symbolStack = new $Symbol$[INITIAL_CAPACITY];
+ private int symbolStackLength = 0;
+
+ private int[] stateStack = new int[INITIAL_CAPACITY];
+ private int[] symbolStackPositionStack = new int[INITIAL_CAPACITY];
+ private int stateStackLength = 0;
+
+ // For reduce
+ private int reductionLength;
+
+ protected int length() {
+ return reductionLength;
+ }
+
+ protected $Symbol$ get(int i) {
+ if(i < 0 || i >= reductionLength)
+ throw new IndexOutOfBoundsException();
+ return symbolStack[symbolStackLength+i];
+ }
+
+ private String parseErrorDescription(int state, $Token$ token, int tokenId) {
+ StringBuilder b = new StringBuilder();
+ b.append("Unexpected token '").append(token)
+ .append("' (").append(TERMINAL_NAMES[tokenId])
+ .append("). Expected one of ");
+ ArrayList<String> possibleTerminals = new ArrayList<String>();
+ for(int i=0;i<TERMINAL_COUNT;++i)
+ if(getAction(state, i) != ERROR_ACTION)
+ possibleTerminals.add(TERMINAL_NAMES[i]);
+ Collections.sort(possibleTerminals);
+ for(int i=0;i<possibleTerminals.size();++i) {
+ if(i > 0)
+ b.append(", ");
+ b.append(possibleTerminals.get(i));
+ }
+ b.append('.');
+ return b.toString();
+ }
+
+ protected abstract RuntimeException syntaxError($Token$ token, String description);
+
+ private static String describeAction(boolean isGoto, int action) {
+ if(action == ERROR_ACTION)
+ return "ERROR";
+ if(action == ACCEPT_ACTION)
+ return "ACCEPT";
+ StringBuilder b = new StringBuilder();
+ if(isGoto)
+ b.append("GOTO ");
+ else {
+ if((action & REDUCE_MASK) != 0) {
+ action ^= REDUCE_MASK;
+ b.append("REDUCE");
+ }
+ else
+ b.append("SHIFT");
+ }
+ if((action & POP_MASK) != 0) {
+ action ^= POP_MASK;
+ b.append(" POP");
+ }
+ if((action & PUSH_MASK) != 0) {
+ action ^= PUSH_MASK;
+ b.append(" PUSH");
+ }
+ b.append(' ').append(action);
+ return b.toString();
+ }
+
+ private void printState(int state) {
+ System.out.print("state=" + state + ":");
+ for(int i=symbolStackLength-1,j=stateStackLength-1;i>=0;--i) {
+ Object s = symbolStack[i];
+ if(s instanceof Token)
+ System.out.print(" " + TERMINAL_NAMES[((Token)s).id]);
+ else if(s == null)
+ System.out.print(" null");
+ else
+ System.out.print(" " + s.getClass().getSimpleName());
+ while(j>=0 && symbolStackPositionStack[j]==i)
+ System.out.print(" (" + stateStack[j--] + ")");
+ }
+ System.out.println();
+ }
+
+ private $Symbol$ parse(int state) {
+ while(true) {
+ $Token$ token = nextToken();
+ int tokenId = token.$tokenId$;
+ if(TRACE)
+ System.out.println("---> token " + TERMINAL_NAMES[tokenId] + " \"" + token.text + "\" <---");
+ while(true) {
+ if(TRACE)
+ printState(state);
+ short action = getAction(state, tokenId);
+ if(TRACE)
+ System.out.println(" -> action=" + describeAction(false, action));
+ //System.out.println(STATE_DESCRIPTIONS[state]);
+ if((action & REDUCE_MASK) != 0) {
+ if(action == ACCEPT_ACTION)
+ return symbolStack[symbolStackLength-1];
+ if(action == ERROR_ACTION)
+ throw syntaxError(token, parseErrorDescription(state, token, tokenId));
+ int popAmount = (action >>> 13)&3;
+ if(TRACE) {
+ if(popAmount > 0)
+ System.out.println(" POP " + popAmount);
+ }
+ stateStackLength -= popAmount;
+ action &= STATE_MASK;
+
+ int reductionBegin = symbolStackPositionStack[--stateStackLength];
+
+ reductionLength = symbolStackLength-reductionBegin;
+ symbolStackLength = reductionBegin;
+
+ if(symbolStackLength == symbolStack.length)
+ symbolStack = Arrays.copyOf(symbolStack, symbolStackLength*2);
+ $Symbol$ symbol = reduce(action);
+ postReduce(symbol);
+ symbolStack[symbolStackLength] = symbol;
+
+ state = stateStack[stateStackLength];
+ if(TRACE) {
+ ++symbolStackLength;
+ printState(state);
+ --symbolStackLength;
+ System.out.println(" nonterminal=" + NONTERMINAL_NAMES[PRODUCT_LHS[action]]);
+ }
+ action = getGoto(state, PRODUCT_LHS[action]);
+ if(TRACE)
+ System.out.println(" -> action=" + describeAction(true, action));
+
+ // Pop state
+ if((action & POP_MASK) != 0) {
+ --stateStackLength;
+ }
+ // Push state
+ if((action & PUSH_MASK) != 0) {
+ if(stateStackLength == stateStack.length) {
+ stateStack = Arrays.copyOf(stateStack, stateStackLength*2);
+ symbolStackPositionStack = Arrays.copyOf(symbolStackPositionStack, stateStackLength*2);
+ }
+ symbolStackPositionStack[stateStackLength] = symbolStackLength;
+ stateStack[stateStackLength++] = state;
+ }
+ state = action & STATE_MASK;
+ ++symbolStackLength;
+ }
+ else {
+ // Pop state
+ if((action & POP_MASK) != 0) {
+ --stateStackLength;
+ }
+ // Push state
+ if((action & PUSH_MASK) != 0) {
+ if(stateStackLength == stateStack.length) {
+ stateStack = Arrays.copyOf(stateStack, stateStackLength*2);
+ symbolStackPositionStack = Arrays.copyOf(symbolStackPositionStack, stateStackLength*2);
+ }
+ symbolStackPositionStack[stateStackLength] = symbolStackLength;
+ stateStack[stateStackLength++] = state;
+ }
+
+ // New state
+ state = action & STATE_MASK;
+
+ // Push symbol
+ if(symbolStackLength == symbolStack.length)
+ symbolStack = Arrays.copyOf(symbolStack, symbolStackLength*2);
+ symbolStack[symbolStackLength++] = token;
+ break;
+ }
+ }
+ }
+ }
+
+$parseMethods$
+
+ protected $Symbol$ reduce(int productionId) {
+ try {
+ switch(productionId) {
+$reduceCases$
+ default:
+ throw new RuntimeException("Internal parser error.");
+ }
+ } catch($Exception$ e) {
+ StringBuilder b = new StringBuilder();
+ b.append("Failed to reduce");
+ for(int i=0;i<length();++i) {
+ Object obj = get(i);
+ b.append("\n (").append(i).append(") \"").append(obj).append('\"');
+ if(obj instanceof $Token$)
+ b.append(" (").append(TERMINAL_NAMES[(($Token$)obj).$tokenId$]).append(")");
+ else
+ b.append(" [").append(obj.getClass().getSimpleName()).append("]");
+ }
+ throw new RuntimeException(b.toString(), e);
+ }
+ }
+
+$reduceMethods$
+ protected void postReduce($Symbol$ reduced) {
+ }
+
+}