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 = 368; private static final int TERMINAL_COUNT = 88; private static final int NONTERMINAL_COUNT = 52; private static final int PRODUCT_COUNT = 142; 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[6820]; private static final int[] ERROR_TABLE = new int[1012]; 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[1953]; 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", "MODULE", "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", "RULESET", "IMPORT", "INCLUDE", "AS", "LPAREN", "RPAREN", "HIDING", "ARROW", "COLON", "MINUS", "SYMBOL", "LESS", "GREATER", "SEPARATED_DOT", "ESCAPED_ID", "LAMBDA", "LAMBDA_MATCH", "LET", "IF", "MATCH", "DO", "MDO", "EDO", "ENFORCE", "BLANK", "FLOAT", "LBRACKET", "ESCAPED_SYMBOL", "CHAR", "WHEN", "ATTACHED_HASH", "SELECT", "SELECT_FIRST", "SELECT_DISTINCT", "TRANSFORMATION", "EQ", "CHR_SELECT", "ATTACHED_DOT", "IN", "THEN", "ELSE", "WITH", "RBRACKET", "DOTDOT", "AT", "SUSPEND_STRING", "CONTINUE_STRING", "BINDS", "IMPLIES", "THEN_AFTER_WHEN", "CONSTRAINT", "BY", "QUERY_OP", "FORALL", "DOUBLE_LESS", "DOUBLE_GREATER", "COMMENT", "EOL", "EOF" }; public static final String[] NONTERMINAL_NAMES = new String[] { "module", "commands", "import", "type", "exp", "equationBlock", "declaration", "command", "statement", "declarations", "field", "var", "bexp", "rhs", "constructor", "context", "fundeps", "atype", "aexp", "ruleDeclarations", "statements", "importSpec", "importItem", "fieldDeclaration", "guardedExpEq", "fundep", "ruleDeclaration", "query", "lexp", "symbol", "faexp", "accessor", "case", "queryBlock", "verboseChrQuery", "stringLiteral", "symbolWithoutMinus", "listQualifier", "chrQuery", "chrQueryPart", "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(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 Object parse(int state) { while(true) { Token token = nextToken(); int tokenId = token.id; 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); Object 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; } } } } public Object parseModule() { return parse(0); } public Object parseCommands() { return parse(352); } public Object parseImport() { return parse(360); } public Object parseType() { return parse(362); } public Object parseExp() { return parse(364); } public Object parseEquationBlock() { return parse(366); } 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 reduceEquationBlock(); case 7: return reduceModuleHeader(); 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 reduceRulesetDefinition(); case 25: return reduceStatementCommand(); case 26: return reduceImportCommand(); case 27: return reduceGuardStatement(); case 28: return reduceLetStatement(); case 29: return reduceBindStatement(); case 30: return reduceRuleStatement(); case 31: return reduceCHRStatement(); case 32: return reduceVerboseCHRStatement(); case 33: return reduceConstraintStatement(); case 34: return reduceLocalInclude(); case 35: return reduceDeclarations(); case 36: return reduceField(); case 37: return reduceFieldShorthand(); case 38: return reduceWildcard(); case 39: return reduceVarId(); case 40: return reduceEscapedSymbol(); case 41: return reduceTupleConstructor(); case 42: return reduceBinary(); case 43: return reduceSimpleRhs(); case 44: return reduceGuardedRhs(); case 45: return reduceConstructor(); case 46: return reduceRecordConstructor(); case 47: return reduceContext(); case 48: return reduceFundeps(); case 49: return reduceTypeVar(); case 50: return reducePlainEffect(); case 51: return reduceTupleType(); case 52: return reduceListType(); case 53: return reduceListTypeConstructor(); case 54: return reduceTupleTypeConstructor(); case 55: return reduceLambda(); case 56: return reduceLambdaMatch(); case 57: return reduceLet(); case 58: return reduceIf(); case 59: return reduceMatch(); case 60: return reduceDo(); case 61: return reduceSelect(); case 62: return reduceCHRSelect(); case 63: return reduceEnforce(); case 64: return reduceVar(); case 65: return reduceHashedId(); case 66: return reduceBlank(); case 67: return reduceInteger(); case 68: return reduceFloat(); case 69: return reduceString(); case 70: return reduceChar(); case 71: return reduceTuple(); case 72: return reduceViewPattern(); case 73: return reduceRightSection(); case 74: return reduceLeftSection(); case 75: return reduceListLiteral(); case 76: return reduceRange(); case 77: return reduceListComprehension(); case 78: return reduceAs(); case 79: return reduceRecord(); case 80: return reduceTransformation(); case 81: return reduceEq(); case 82: return reduceRuleDeclarations(); case 83: return reduceStatements(); case 84: return reduceImportShowing(); case 85: return reduceImportHiding(); case 86: return reduceImportValueItem(); case 87: return reduceFieldDescription(); case 88: return reduceGuardedExpEq(); case 89: return reduceFundep(); case 90: return reduceQueryRuleDeclaration(); case 91: return reduceAnnotation(); case 92: return reduceGuardQuery(); case 93: return reduceEqualsQuery(); case 94: return reduceBindQuery(); case 95: return reduceCompositeQuery(); case 96: return reduceApply(); case 97: return reduceSymbol(); case 98: return reduceEscapedId(); case 99: return reduceMinus(); case 100: return reduceLess(); case 101: return reduceGreater(); case 102: return reduceDoubleLess(); case 103: return reduceDoubleGreater(); case 104: return reduceDot(); case 105: return reduceFieldAccess(); case 106: return reduceIdAccessor(); case 107: return reduceStringAccessor(); case 108: return reduceExpAccessor(); case 109: return reduceCase(); case 110: return reduceQueryBlock(); case 111: return reduceVerboseCHRConjunction(); case 112: return reduceStringLiteral(); case 113: return reduceSymbol(); case 114: return reduceEscapedId(); case 115: return reduceLess(); case 116: return reduceGreater(); case 117: return reduceDot(); case 118: return reduceGuardQualifier(); case 119: return reduceLetQualifier(); case 120: return reduceBindQualifier(); case 121: return reduceThenQualifier(); case 122: return reduceCHRConjunction(); case 123: return reduceCHRAtom(); case 124: return reduceCHREquals(); case 125: return reduceCHRBinds(); case 126: return reduceSimpleCaseRhs(); case 127: return reduceGuardedCaseRhs(); case 128: return reduceGuardedExpArrow(); case 129: return reduceGuardEquation(); case 130: return reduceBasicEquation(); case 131: return reduceEffect(); case 132: return reduceJustEtype(); case 133: return reduceForAll(); case 134: return reduceApplyType(); case 135: return reduceDummy(); default: throw new RuntimeException("Internal parser error."); } } catch(SCLSyntaxErrorException e) { StringBuilder b = new StringBuilder(); b.append("Failed to reduce"); for(int i=0;i