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>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 possibleTerminals = new ArrayList(); for(int i=0;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