3 import java.io.DataInputStream;
4 import java.io.IOException;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
11 public abstract class $class$ {
12 public static final boolean TRACE = false;
14 private static final int INITIAL_CAPACITY = 16;
15 private static final int STATE_COUNT = $stateCount$;
16 private static final int TERMINAL_COUNT = $terminalCount$;
17 private static final int NONTERMINAL_COUNT = $nonterminalCount$;
18 private static final int PRODUCT_COUNT = $productCount$;
20 private static final int[] ACTION_ROW_ID = new int[STATE_COUNT];
21 private static final int[] ACTION_COLUMN_ID = new int[TERMINAL_COUNT];
22 private static final short[] ACTION_TABLE = new short[$actionTableLength$];
23 private static final int[] ERROR_TABLE = new int[$errorTableLength$];
24 private static final int[] GOTO_ROW_ID = new int[STATE_COUNT];
25 private static final int[] GOTO_COLUMN_ID = new int[NONTERMINAL_COUNT];
26 private static final short[] GOTO_TABLE = new short[$gotoTableLength$];
27 private static final int[] PRODUCT_LHS = new int[PRODUCT_COUNT];
29 private static final short STATE_MASK = (short)0x0fff;
30 private static final short REDUCE_MASK = (short)0x8000;
31 private static final short POP_MASK = (short)0x4000;
32 private static final short PUSH_MASK = (short)0x2000;
33 private static final short ERROR_ACTION = (short)0xffff;
34 private static final short ACCEPT_ACTION = (short)0xfffe;
36 public static final String[] TERMINAL_NAMES = new String[] {
40 public static final String[] NONTERMINAL_NAMES = new String[] {
46 DataInputStream input = new DataInputStream($class$.class.getResourceAsStream("$class$.dat"));
47 for(int i=0;i<ACTION_ROW_ID.length;++i)
48 ACTION_ROW_ID[i] = input.readInt();
49 for(int i=0;i<ACTION_COLUMN_ID.length;++i)
50 ACTION_COLUMN_ID[i] = input.readInt();
51 for(int i=0;i<ACTION_TABLE.length;++i)
52 ACTION_TABLE[i] = input.readShort();
53 for(int i=0;i<ERROR_TABLE.length;++i)
54 ERROR_TABLE[i] = input.readInt();
55 for(int i=0;i<GOTO_ROW_ID.length;++i)
56 GOTO_ROW_ID[i] = input.readInt();
57 for(int i=0;i<GOTO_COLUMN_ID.length;++i)
58 GOTO_COLUMN_ID[i] = input.readInt();
59 for(int i=0;i<GOTO_TABLE.length;++i)
60 GOTO_TABLE[i] = input.readShort();
61 for(int i=0;i<PRODUCT_LHS.length;++i)
62 PRODUCT_LHS[i] = input.readInt();
64 } catch(IOException e) {
69 private static short getAction(int state, int symbol) {
70 int id = TERMINAL_COUNT*state + symbol;
71 if( ((ERROR_TABLE[id>>5] >> (id&31))&1) != 0 )
73 return ACTION_TABLE[ACTION_ROW_ID[state] + ACTION_COLUMN_ID[symbol]];
76 private static short getGoto(int state, int symbol) {
77 return GOTO_TABLE[GOTO_ROW_ID[state] + GOTO_COLUMN_ID[symbol]];
80 protected abstract $Token$ nextToken();
82 private $Symbol$[] symbolStack = new $Symbol$[INITIAL_CAPACITY];
83 private int symbolStackLength = 0;
85 private int[] stateStack = new int[INITIAL_CAPACITY];
86 private int[] symbolStackPositionStack = new int[INITIAL_CAPACITY];
87 private int stateStackLength = 0;
90 private int reductionLength;
92 protected int length() {
93 return reductionLength;
96 protected $Symbol$ get(int i) {
97 if(i < 0 || i >= reductionLength)
98 throw new IndexOutOfBoundsException();
99 return symbolStack[symbolStackLength+i];
102 private String parseErrorDescription(int state, $Token$ token, int tokenId) {
103 StringBuilder b = new StringBuilder();
104 b.append("Unexpected token '").append(token)
105 .append("' (").append(TERMINAL_NAMES[tokenId])
106 .append("). Expected one of ");
107 ArrayList<String> possibleTerminals = new ArrayList<String>();
108 for(int i=0;i<TERMINAL_COUNT;++i)
109 if(getAction(state, i) != ERROR_ACTION)
110 possibleTerminals.add(TERMINAL_NAMES[i]);
111 Collections.sort(possibleTerminals);
112 for(int i=0;i<possibleTerminals.size();++i) {
115 b.append(possibleTerminals.get(i));
121 protected abstract RuntimeException syntaxError($Token$ token, String description);
123 private static String describeAction(boolean isGoto, int action) {
124 if(action == ERROR_ACTION)
126 if(action == ACCEPT_ACTION)
128 StringBuilder b = new StringBuilder();
132 if((action & REDUCE_MASK) != 0) {
133 action ^= REDUCE_MASK;
139 if((action & POP_MASK) != 0) {
143 if((action & PUSH_MASK) != 0) {
147 b.append(' ').append(action);
151 private void printState(int state) {
152 System.out.print("state=" + state + ":");
153 for(int i=symbolStackLength-1,j=stateStackLength-1;i>=0;--i) {
154 Object s = symbolStack[i];
155 if(s instanceof Token)
156 System.out.print(" " + TERMINAL_NAMES[((Token)s).id]);
158 System.out.print(" null");
160 System.out.print(" " + s.getClass().getSimpleName());
161 while(j>=0 && symbolStackPositionStack[j]==i)
162 System.out.print(" (" + stateStack[j--] + ")");
164 System.out.println();
167 private $Symbol$ parse(int state) {
169 $Token$ token = nextToken();
170 int tokenId = token.$tokenId$;
172 System.out.println("---> token " + TERMINAL_NAMES[tokenId] + " \"" + token.text + "\" <---");
176 short action = getAction(state, tokenId);
178 System.out.println(" -> action=" + describeAction(false, action));
179 //System.out.println(STATE_DESCRIPTIONS[state]);
180 if((action & REDUCE_MASK) != 0) {
181 if(action == ACCEPT_ACTION)
182 return symbolStack[symbolStackLength-1];
183 if(action == ERROR_ACTION)
184 throw syntaxError(token, parseErrorDescription(state, token, tokenId));
185 int popAmount = (action >>> 13)&3;
188 System.out.println(" POP " + popAmount);
190 stateStackLength -= popAmount;
191 action &= STATE_MASK;
193 int reductionBegin = symbolStackPositionStack[--stateStackLength];
195 reductionLength = symbolStackLength-reductionBegin;
196 symbolStackLength = reductionBegin;
198 if(symbolStackLength == symbolStack.length)
199 symbolStack = Arrays.copyOf(symbolStack, symbolStackLength*2);
200 $Symbol$ symbol = reduce(action);
202 symbolStack[symbolStackLength] = symbol;
204 state = stateStack[stateStackLength];
209 System.out.println(" nonterminal=" + NONTERMINAL_NAMES[PRODUCT_LHS[action]]);
211 action = getGoto(state, PRODUCT_LHS[action]);
213 System.out.println(" -> action=" + describeAction(true, action));
216 if((action & POP_MASK) != 0) {
220 if((action & PUSH_MASK) != 0) {
221 if(stateStackLength == stateStack.length) {
222 stateStack = Arrays.copyOf(stateStack, stateStackLength*2);
223 symbolStackPositionStack = Arrays.copyOf(symbolStackPositionStack, stateStackLength*2);
225 symbolStackPositionStack[stateStackLength] = symbolStackLength;
226 stateStack[stateStackLength++] = state;
228 state = action & STATE_MASK;
233 if((action & POP_MASK) != 0) {
237 if((action & PUSH_MASK) != 0) {
238 if(stateStackLength == stateStack.length) {
239 stateStack = Arrays.copyOf(stateStack, stateStackLength*2);
240 symbolStackPositionStack = Arrays.copyOf(symbolStackPositionStack, stateStackLength*2);
242 symbolStackPositionStack[stateStackLength] = symbolStackLength;
243 stateStack[stateStackLength++] = state;
247 state = action & STATE_MASK;
250 if(symbolStackLength == symbolStack.length)
251 symbolStack = Arrays.copyOf(symbolStack, symbolStackLength*2);
252 symbolStack[symbolStackLength++] = token;
261 protected $Symbol$ reduce(int productionId) {
263 switch(productionId) {
266 throw new RuntimeException("Internal parser error.");
268 } catch($Exception$ e) {
269 StringBuilder b = new StringBuilder();
270 b.append("Failed to reduce");
271 for(int i=0;i<length();++i) {
273 b.append("\n (").append(i).append(") \"").append(obj).append('\"');
274 if(obj instanceof $Token$)
275 b.append(" (").append(TERMINAL_NAMES[(($Token$)obj).$tokenId$]).append(")");
277 b.append(" [").append(obj.getClass().getSimpleName()).append("]");
279 throw new RuntimeException(b.toString(), e);
284 protected void postReduce($Symbol$ reduced) {