package org.simantics.scl.compiler.internal.parsing.parser; 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; import org.simantics.scl.compiler.internal.parsing.Token; public abstract class SCLParser { public static final boolean TRACE = false; private static final int INITIAL_CAPACITY = 16; private static final int STATE_COUNT = 323; private static final int TERMINAL_COUNT = 79; private static final int NONTERMINAL_COUNT = 49; private static final int PRODUCT_COUNT = 126; 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[5508]; private static final int[] ERROR_TABLE = new int[798]; 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[1620]; 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[] { "SEMICOLON", "LBRACE", "RBRACE", "COMMA", "HASTYPE", "DATA", "ID", "EQUALS", "BAR", "TYPE", "CLASS", "WHERE", "INSTANCE", "DERIVING", "BEGIN_STRING", "END_STRING", "ANNOTATION_ID", "INFIX", "INFIXL", "INFIXR", "INTEGER", "IMPORTJAVA", "EFFECT", "RULE", "ABSTRACT_RULE", "EXTENDS", "MAPPING_RELATION", "FOLLOWS", "IMPORT", "INCLUDE", "AS", "LPAREN", "RPAREN", "HIDING", "ARROW", "COLON", "WITH", "MINUS", "SYMBOL", "LESS", "GREATER", "SEPARATED_DOT", "ESCAPED_ID", "LAMBDA", "LET", "IF", "MATCH", "DO", "MDO", "ENFORCE", "BLANK", "FLOAT", "LBRACKET", "ESCAPED_SYMBOL", "CHAR", "WHEN", "ATTACHED_HASH", "SELECT", "SELECT_FIRST", "SELECT_DISTINCT", "TRANSFORMATION", "EQ", "ATTACHED_DOT", "IN", "THEN", "ELSE", "RBRACKET", "DOTDOT", "AT", "SUSPEND_STRING", "CONTINUE_STRING", "BINDS", "BY", "QUERY_OP", "IMPLIES", "FORALL", "COMMENT", "EOL", "EOF" }; public static final String[] NONTERMINAL_NAMES = new String[] { "module", "commands", "import", "type", "exp", "equationBlock", "declaration", "command", "statement", "declarations", "var", "bexp", "rhs", "constructor", "context", "fundeps", "atype", "aexp", "ruleDeclarations", "importSpec", "importItem", "fieldDeclaration", "statements", "guardedExpEq", "fundep", "ruleDeclaration", "query", "queryBlock", "lexp", "symbol", "faexp", "accessor", "case", "stringLiteral", "symbolWithoutMinus", "listQualifier", "field", "caseRhs", "guardedExpArrow", "equation", "etype", "btype", "dummy", "init$6", "init$5", "init$4", "init$3", "init$2", "init$1" }; static { try { DataInputStream input = new DataInputStream(SCLParser.class.getResourceAsStream("SCLParser.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 Object[] symbolStack = new Object[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 Object 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(int action) { if(action == ERROR_ACTION) return "ERROR"; if(action == ACCEPT_ACTION) return "ACCEPT"; StringBuilder b = new StringBuilder(); 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 Object parse(int state) { while(true) { Token token = nextToken(); int tokenId = token.id; while(true) { short action = getAction(state, tokenId); if(TRACE) { System.out.println("state=" + state + ", tokenId=" + TERMINAL_NAMES[tokenId] + ", action=" + describeAction(action)); System.out.print(" "); 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 System.out.print(" " + s.getClass().getSimpleName()); while(j>=0 && symbolStackPositionStack[j]==i) System.out.print(" (" + stateStack[j--] + ")"); } System.out.println(); } //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)); stateStackLength -= (action >>> 13)&3; action &= STATE_MASK; int reductionBegin = symbolStackPositionStack[--stateStackLength]; reductionLength = symbolStackLength-reductionBegin; symbolStackLength = reductionBegin; if(symbolStackLength == symbolStack.length) symbolStack = Arrays.copyOf(symbolStack, symbolStackLength*2); Object symbol = reduce(action); postReduce(symbol); symbolStack[symbolStackLength] = symbol; state = stateStack[stateStackLength]; action = getGoto(state, PRODUCT_LHS[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; } } } } public Object parseModule() { return parse(0); } public Object parseCommands() { return parse(308); } public Object parseImport() { return parse(315); } public Object parseType() { return parse(317); } public Object parseExp() { return parse(319); } public Object parseEquationBlock() { return parse(321); } protected Object reduce(int productionId) { try { switch(productionId) { case 0: return reduceModule(); case 1: return reduceOneCommand(); case 2: return reduceManyCommands(); case 3: return reduceImport(); case 4: return reduceArrow(); case 5: return reduceLocalTypeAnnotation(); case 6: return reduceEntityTypeAnnotation(); case 7: return reduceEquationBlock(); case 8: return reduceTypeAnnotation(); case 9: return reduceValueDefinition(); case 10: return reduceDataDefinition(); case 11: return reduceTypeDefinition(); case 12: return reduceClassDefinition(); case 13: return reduceInstanceDefinition(); case 14: return reduceDerivingInstanceDefinition(); case 15: return reduceDocumentationString(); case 16: return reduceAnnotation(); case 17: return reducePrecedenceDefinition(); case 18: return reduceJustImport(); case 19: return reduceImportJava(); case 20: return reduceEffectDefinition(); case 21: return reduceRuleDefinition(); case 22: return reduceMappingRelationDefinition(); case 23: return reduceRelationDefinition(); case 24: return reduceStatementCommand(); case 25: return reduceImportCommand(); case 26: return reduceGuardStatement(); case 27: return reduceLetStatement(); case 28: return reduceBindStatement(); case 29: return reduceRuleStatement(); case 30: return reduceDeclarations(); case 31: return reduceVarId(); case 32: return reduceEscapedSymbol(); case 33: return reduceTupleConstructor(); case 34: return reduceBinary(); case 35: return reduceSimpleRhs(); case 36: return reduceGuardedRhs(); case 37: return reduceConstructor(); case 38: return reduceRecordConstructor(); case 39: return reduceContext(); case 40: return reduceFundeps(); case 41: return reduceTypeVar(); case 42: return reduceTupleType(); case 43: return reduceListType(); case 44: return reduceListTypeConstructor(); case 45: return reduceTupleTypeConstructor(); case 46: return reduceLambda(); case 47: return reduceLet(); case 48: return reduceIf(); case 49: return reduceMatch(); case 50: return reduceDo(); case 51: return reduceSelect(); case 52: return reduceEnforce(); case 53: return reduceWhen(); case 54: return reduceVar(); case 55: return reduceHashedId(); case 56: return reduceBlank(); case 57: return reduceInteger(); case 58: return reduceFloat(); case 59: return reduceString(); case 60: return reduceChar(); case 61: return reduceTuple(); case 62: return reduceRightSection(); case 63: return reduceLeftSection(); case 64: return reduceListLiteral(); case 65: return reduceRange(); case 66: return reduceListComprehension(); case 67: return reduceAs(); case 68: return reduceRecord(); case 69: return reduceTransformation(); case 70: return reduceEq(); case 71: return reduceRuleDeclarations(); case 72: return reduceImportShowing(); case 73: return reduceImportHiding(); case 74: return reduceImportValueItem(); case 75: return reduceFieldDescription(); case 76: return reduceStatements(); case 77: return reduceGuardedExpEq(); case 78: return reduceFundep(); case 79: return reduceQueryRuleDeclaration(); case 80: return reduceAnnotation(); case 81: return reduceGuardQuery(); case 82: return reduceEqualsQuery(); case 83: return reduceBindQuery(); case 84: return reduceCompositeQuery(); case 85: return reduceQueryBlock(); case 86: return reduceApply(); case 87: return reduceSymbol(); case 88: return reduceEscapedId(); case 89: return reduceMinus(); case 90: return reduceLess(); case 91: return reduceGreater(); case 92: return reduceDot(); case 93: return reduceFieldAccess(); case 94: return reduceIdAccessor(); case 95: return reduceStringAccessor(); case 96: return reduceExpAccessor(); case 97: return reduceCase(); case 98: return reduceStringLiteral(); case 99: return reduceSymbol(); case 100: return reduceEscapedId(); case 101: return reduceLess(); case 102: return reduceGreater(); case 103: return reduceDot(); case 104: return reduceGuardQualifier(); case 105: return reduceLetQualifier(); case 106: return reduceBindQualifier(); case 107: return reduceThenQualifier(); case 108: return reduceField(); case 109: return reduceFieldShorthand(); case 110: return reduceSimpleCaseRhs(); case 111: return reduceGuardedCaseRhs(); case 112: return reduceGuardedExpArrow(); case 113: return reduceGuardEquation(); case 114: return reduceBasicEquation(); case 115: return reduceEffect(); case 116: return reduceJustEtype(); case 117: return reduceForAll(); case 118: return reduceApplyType(); case 119: return reduceDummy1(); default: throw new RuntimeException("Internal parser error."); } } catch(SCLSyntaxErrorException e) { StringBuilder b = new StringBuilder(); b.append("Failed to reduce"); for(int i=0;i