package org.simantics.scl.compiler.internal.parsing.parser; import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.precedence.Associativity; import org.simantics.scl.compiler.common.precedence.Precedence; import org.simantics.scl.compiler.constants.CharacterConstant; import org.simantics.scl.compiler.constants.StringConstant; import org.simantics.scl.compiler.elaboration.equation.EqBasic; import org.simantics.scl.compiler.elaboration.equation.EqGuard; import org.simantics.scl.compiler.elaboration.equation.Equation; import org.simantics.scl.compiler.elaboration.expressions.Case; import org.simantics.scl.compiler.elaboration.expressions.EApply; import org.simantics.scl.compiler.elaboration.expressions.EAsPattern; import org.simantics.scl.compiler.elaboration.expressions.EBinary; import org.simantics.scl.compiler.elaboration.expressions.EBinaryRightSide; import org.simantics.scl.compiler.elaboration.expressions.EBlock; import org.simantics.scl.compiler.elaboration.expressions.EConstant; import org.simantics.scl.compiler.elaboration.expressions.EEnforce; import org.simantics.scl.compiler.elaboration.expressions.EEquations; import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess; import org.simantics.scl.compiler.elaboration.expressions.EIf; import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELambda; import org.simantics.scl.compiler.elaboration.expressions.EListComprehension; import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; import org.simantics.scl.compiler.elaboration.expressions.ELiteral; import org.simantics.scl.compiler.elaboration.expressions.EMatch; import org.simantics.scl.compiler.elaboration.expressions.ERange; import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral; import org.simantics.scl.compiler.elaboration.expressions.ERecord; import org.simantics.scl.compiler.elaboration.expressions.ESelect; import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda; import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral; import org.simantics.scl.compiler.elaboration.expressions.ETransformation; import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation; import org.simantics.scl.compiler.elaboration.expressions.EVar; import org.simantics.scl.compiler.elaboration.expressions.EVariable; import org.simantics.scl.compiler.elaboration.expressions.EViewPattern; import org.simantics.scl.compiler.elaboration.expressions.Expression; import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression; import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup; import org.simantics.scl.compiler.elaboration.expressions.Variable; import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor; import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor; import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor; import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor; import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement; import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement; import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement; import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement; import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement; import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement; import org.simantics.scl.compiler.elaboration.expressions.block.Statement; import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment; import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator; import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard; import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier; import org.simantics.scl.compiler.elaboration.expressions.list.ListSeq; import org.simantics.scl.compiler.elaboration.expressions.list.ListThen; import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; import org.simantics.scl.compiler.elaboration.java.Builtins; import org.simantics.scl.compiler.elaboration.query.QAlternative; import org.simantics.scl.compiler.elaboration.query.QConjunction; import org.simantics.scl.compiler.elaboration.query.QDisjunction; import org.simantics.scl.compiler.elaboration.query.QNegation; import org.simantics.scl.compiler.elaboration.query.Query; import org.simantics.scl.compiler.elaboration.query.pre.QPreBinds; import org.simantics.scl.compiler.elaboration.query.pre.QPreEquals; import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.internal.parsing.Symbol; import org.simantics.scl.compiler.internal.parsing.Token; import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst; import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst; import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst; import org.simantics.scl.compiler.internal.parsing.declarations.DDataAst; import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst; import org.simantics.scl.compiler.internal.parsing.declarations.DDocumentationAst; import org.simantics.scl.compiler.internal.parsing.declarations.DEffectAst; import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst; import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst; import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst; import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst; import org.simantics.scl.compiler.internal.parsing.declarations.DModuleHeader; import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst; import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst; import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst; import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst; import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst; import org.simantics.scl.compiler.internal.parsing.declarations.FieldDescription; import org.simantics.scl.compiler.internal.parsing.declarations.FundepAst; import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException; import org.simantics.scl.compiler.internal.parsing.types.TApplyAst; import org.simantics.scl.compiler.internal.parsing.types.TEffectAst; import org.simantics.scl.compiler.internal.parsing.types.TForAllAst; import org.simantics.scl.compiler.internal.parsing.types.TFunctionAst; import org.simantics.scl.compiler.internal.parsing.types.TListAst; import org.simantics.scl.compiler.internal.parsing.types.TPredAst; import org.simantics.scl.compiler.internal.parsing.types.TTupleAst; import org.simantics.scl.compiler.internal.parsing.types.TVarAst; import org.simantics.scl.compiler.internal.parsing.types.TypeAst; import org.simantics.scl.compiler.module.ImportDeclaration; import org.simantics.scl.compiler.types.Types; public class SCLParserImpl extends SCLParser { private final SCLPostLexer lexer; private SCLParserOptions options; public SCLParserImpl(Reader reader) { lexer = new SCLPostLexer(reader); } public void setParserOptions(SCLParserOptions options) { this.options = options; lexer.setParserOptions(options); } public boolean isEmpty() throws Exception { return lexer.peekToken().id == SCLTerminals.EOF; } @Override protected Token nextToken() { try { Token token = lexer.nextToken(); /*System.out.println("TOKEN " + token.text + " (" + TERMINAL_NAMES[token.id] + ")" + " [" + Locations.beginOf(token.location) + ".." + Locations.endOf(token.location) + "]");*/ return token; } catch(Exception e) { if(e instanceof RuntimeException) throw (RuntimeException)e; else throw new RuntimeException(e); } } @Override protected Object reduceDeclarations() { ArrayList declarations = new ArrayList(length()/2); for(int i=1;i declarations = new ArrayList(length()/2+1); for(int i=0;i parameters = new ArrayList(); while(i < length()) { Token token = (Token)get(i++); if(token.id != SCLTerminals.ID) break; parameters.add(token.text); } ArrayList constructors = new ArrayList(); for(;i < length();i+=2) constructors.add((ConstructorAst)get(i)); return new DDataAst( ((Token)get(1)).text, parameters.toArray(new String[parameters.size()]), constructors.toArray(new ConstructorAst[constructors.size()]), new String[0] ); } @Override protected Object reduceTypeDefinition() { int i=2; ArrayList parameters = new ArrayList(); while(true) { Token token = (Token)get(i++); if(token.id != SCLTerminals.ID) break; parameters.add(token.text); } return new DTypeAst( ((Token)get(1)).text, parameters.toArray(new String[parameters.size()]), (TypeAst)get(i) ); } @SuppressWarnings("unchecked") @Override protected Object reduceClassDefinition() { int i=1; ArrayList context; if(get(i) instanceof Token) context = new ArrayList(0); else context = (ArrayList)get(i++); String name = ((Token)get(i++)).text; ArrayList parameters = new ArrayList(); while(i < length()) { Token token = (Token)get(i); if(token.id != SCLTerminals.ID) break; parameters.add(token.text); ++i; } ArrayList declarations = null; FundepAst[] fundeps = FundepAst.EMPTY_ARRAY; while(i < length()) { Token token = (Token)get(i++); if(token.id == SCLTerminals.WHERE) { declarations = (ArrayList)get(i++); } else if(token.id == SCLTerminals.BAR) { fundeps = (FundepAst[])get(i++); } else throw new InternalCompilerError(); } return new DClassAst(context, name, parameters.toArray(new String[parameters.size()]), fundeps, declarations); } @Override protected Object reduceFundep() { String[] from = new String[length()-2]; for(int i=0;i context; if(get(i) instanceof Token) context = new ArrayList(0); else context = (ArrayList)get(i++); Token nameToken = (Token)get(i++); EVar name = new EVar(nameToken.location, nameToken.text); ArrayList parameters = new ArrayList(); while(i < length()) { Object symbol = get(i++); if(symbol instanceof Token) break; parameters.add((TypeAst)symbol); } ArrayList declarations = null; if(i < length()) declarations = (ArrayList)get(i); return new DInstanceAst(context, name, parameters.toArray(new TypeAst[parameters.size()]), declarations); } @SuppressWarnings("unchecked") @Override protected Object reduceDerivingInstanceDefinition() { int i=2; ArrayList context; if(get(i) instanceof Token) context = new ArrayList(0); else context = (ArrayList)get(i++); Token nameToken = (Token)get(i++); EVar name = new EVar(nameToken.location, nameToken.text); ArrayList parameters = new ArrayList(); while(i < length()) { Object symbol = get(i++); parameters.add((TypeAst)symbol); } return new DDerivingInstanceAst(context, name, parameters.toArray(new TypeAst[parameters.size()])); } @Override protected Object reduceDocumentationString() { return new DDocumentationAst(((Token)get(1)).text); } @Override protected Object reduceAnnotation() { ArrayList parameters = new ArrayList(length()-1); for(int i=1;i)get(4)); } @Override protected Object reduceEffectDefinition() { return new DEffectAst( ((Token)get(1)).text, ((Token)get(3)).text, ((Token)get(5)).text); } @Override protected Object reduceVarId() { return new EVar(((Token)get(0)).text); } @Override protected Object reduceEscapedSymbol() { return new EVar(((Token)get(0)).text); } @Override protected Object reduceTupleTypeConstructor() { return new TVarAst(Types.tupleConstructor(length()-1).name); } @Override protected Object reduceArrow() { int i=length()-1; TypeAst result = (TypeAst)get(i); i-=2; while(i >= 0) { if( ((Token)get(i+1)).text.equals("=>") ) result = new TPredAst((TypeAst)get(i), result); else result = new TFunctionAst((TypeAst)get(i), result); i-=2; } return result; } @Override protected Object reduceBinary() { if(length() == 1) return get(0); int i=0; EVar negation = null; if(get(i) instanceof Token) { Token token = (Token)get(i++); negation = new EVar(token.location, token.text); } EBinary binary = new EBinary((Expression)get(i++), negation); while(i < length()) { EVar operator = (EVar)get(i++); Expression right = (Expression)get(i++); binary.rights.add(new EBinaryRightSide(operator, right)); } return binary; } @Override protected Object reduceSimpleRhs() { if(length() == 2) return get(1); else { EBlock block = (EBlock)get(3); Expression expression = (Expression)get(1); block.addStatement(new GuardStatement(expression)); block.location = Locations.location(Locations.beginOf(expression.location), Locations.endOf(block.location)); return block; } } private GuardedExpressionGroup reduceGuardedExpressionGroup(int length) { GuardedExpression[] expressions = new GuardedExpression[length]; for(int i=0;i 2 && get(length-2) instanceof Token) { EBlock block = (EBlock)get(length-1); block.addStatement(new GuardStatement(reduceGuardedExpressionGroup(length-2))); block.location = Locations.NO_LOCATION; return block; } else return reduceGuardedExpressionGroup(length); } @Override protected Object reduceStatements() { EBlock block = new EBlock(); if(length() > 2) for(int i=1;i result = new ArrayList(length()/2-1); for(int i=1;i effects = new ArrayList(length()/2-1); for(int i=1;i ll = (List)first; first = ll.get(0); } else { Object[] ll = (Object[])first; if(ll.length > 0) first = ll[0]; else first = get(1); } } Object last = get(length()-1); if(!(last instanceof Symbol)) { if(last instanceof List) { List ll = (List)last; last = ll.get(ll.size()-1); } else { Object[] ll = (Object[])last; if(ll.length > 0) last = ll[ll.length-1]; else last = get(length()-2); } } sym.location = (((Symbol)first).location & 0xffffffff00000000L) | (((Symbol)last).location & 0xffffffffL); /*for(int i=0;i " + reduced.getClass().getSimpleName() + " " + Locations.beginOf(sym.location) + "-" + Locations.endOf(sym.location));*/ } @Override protected RuntimeException syntaxError(Token token, String description) { throw new SCLSyntaxErrorException(token.location, description); } @Override protected Object reduceIdAccessor() { return new IdAccessor('.', ((Token)get(0)).text); } @Override protected Object reduceStringAccessor() { return new StringAccessor('.', ((Token)get(1)).text); } @Override protected Object reduceExpAccessor() { return new ExpressionAccessor('.', (Expression)get(1)); } @Override protected Object reduceFieldAccess() { if(length() == 1) return get(0); Expression result = (Expression)get(0); for(int i=2;i declarations = new ArrayList(length()/2); for(int i=1;i= 6) { int extendsCount = (length() - 4) / 2; extendsNames = new String[extendsCount]; for(int i=0;i ruleDeclarations = (ArrayList)get(length()-1); ArrayList section = null; for(Object decl : ruleDeclarations) { if(decl instanceof DAnnotationAst) { DAnnotationAst annotation = (DAnnotationAst)decl; section = rule.getSection(annotation.id.text.substring(1)); } else if(decl instanceof Query) { if(section == null) section = rule.getSection("when"); section.add((Query)decl); } else throw new InternalCompilerError(); } return rule; } @Override protected Object reduceQueryRuleDeclaration() { return get(0); } @Override protected Object reduceMappingRelationDefinition() { TypeAst[] types = new TypeAst[length()-2]; for(int i=0;i)get(2)).toArray()); } @Override protected Object reduceRecord() { FieldAssignment[] fields = new FieldAssignment[length()/2-1]; for(int i=0;i