]> gerrit.simantics Code Review - simantics/platform.git/blob
5498b16b5f0552df54669752cd807e6dde64a53b
[simantics/platform.git] /
1 package org.simantics.scl.compiler.internal.parsing.parser;
2
3 import java.io.Reader;
4 import java.util.ArrayList;
5 import java.util.Arrays;
6 import java.util.List;
7
8 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
9 import org.simantics.scl.compiler.common.precedence.Associativity;
10 import org.simantics.scl.compiler.common.precedence.Precedence;
11 import org.simantics.scl.compiler.constants.CharacterConstant;
12 import org.simantics.scl.compiler.constants.StringConstant;
13 import org.simantics.scl.compiler.elaboration.equation.EqBasic;
14 import org.simantics.scl.compiler.elaboration.equation.EqGuard;
15 import org.simantics.scl.compiler.elaboration.equation.Equation;
16 import org.simantics.scl.compiler.elaboration.expressions.Case;
17 import org.simantics.scl.compiler.elaboration.expressions.EApply;
18 import org.simantics.scl.compiler.elaboration.expressions.EAsPattern;
19 import org.simantics.scl.compiler.elaboration.expressions.EBinary;
20 import org.simantics.scl.compiler.elaboration.expressions.EBinaryRightSide;
21 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
22 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
23 import org.simantics.scl.compiler.elaboration.expressions.EEnforce;
24 import org.simantics.scl.compiler.elaboration.expressions.EEntityTypeAnnotation;
25 import org.simantics.scl.compiler.elaboration.expressions.EEquations;
26 import org.simantics.scl.compiler.elaboration.expressions.EFieldAccess;
27 import org.simantics.scl.compiler.elaboration.expressions.EIf;
28 import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
29 import org.simantics.scl.compiler.elaboration.expressions.ELambda;
30 import org.simantics.scl.compiler.elaboration.expressions.EListComprehension;
31 import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
32 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
33 import org.simantics.scl.compiler.elaboration.expressions.EMatch;
34 import org.simantics.scl.compiler.elaboration.expressions.ERange;
35 import org.simantics.scl.compiler.elaboration.expressions.ERealLiteral;
36 import org.simantics.scl.compiler.elaboration.expressions.ERecord;
37 import org.simantics.scl.compiler.elaboration.expressions.ESelect;
38 import org.simantics.scl.compiler.elaboration.expressions.ESimpleLambda;
39 import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral;
40 import org.simantics.scl.compiler.elaboration.expressions.ETransformation;
41 import org.simantics.scl.compiler.elaboration.expressions.ETypeAnnotation;
42 import org.simantics.scl.compiler.elaboration.expressions.EVar;
43 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
44 import org.simantics.scl.compiler.elaboration.expressions.EViewPattern;
45 import org.simantics.scl.compiler.elaboration.expressions.Expression;
46 import org.simantics.scl.compiler.elaboration.expressions.GuardedExpression;
47 import org.simantics.scl.compiler.elaboration.expressions.GuardedExpressionGroup;
48 import org.simantics.scl.compiler.elaboration.expressions.Variable;
49 import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
50 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
51 import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
52 import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
53 import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
54 import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
55 import org.simantics.scl.compiler.elaboration.expressions.block.ConstraintStatement;
56 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
57 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
58 import org.simantics.scl.compiler.elaboration.expressions.block.RuleStatement;
59 import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
60 import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
61 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
62 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
63 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
64 import org.simantics.scl.compiler.elaboration.expressions.list.ListSeq;
65 import org.simantics.scl.compiler.elaboration.expressions.list.ListThen;
66 import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
67 import org.simantics.scl.compiler.elaboration.java.Builtins;
68 import org.simantics.scl.compiler.elaboration.query.QAlternative;
69 import org.simantics.scl.compiler.elaboration.query.QConjunction;
70 import org.simantics.scl.compiler.elaboration.query.QDisjunction;
71 import org.simantics.scl.compiler.elaboration.query.QNegation;
72 import org.simantics.scl.compiler.elaboration.query.Query;
73 import org.simantics.scl.compiler.elaboration.query.pre.QPreBinds;
74 import org.simantics.scl.compiler.elaboration.query.pre.QPreEquals;
75 import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
76 import org.simantics.scl.compiler.errors.Locations;
77 import org.simantics.scl.compiler.internal.parsing.Symbol;
78 import org.simantics.scl.compiler.internal.parsing.Token;
79 import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
80 import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
81 import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
82 import org.simantics.scl.compiler.internal.parsing.declarations.DDataAst;
83 import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst;
84 import org.simantics.scl.compiler.internal.parsing.declarations.DDocumentationAst;
85 import org.simantics.scl.compiler.internal.parsing.declarations.DEffectAst;
86 import org.simantics.scl.compiler.internal.parsing.declarations.DFixityAst;
87 import org.simantics.scl.compiler.internal.parsing.declarations.DImportJavaAst;
88 import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst;
89 import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
90 import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
91 import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
92 import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
93 import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
94 import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
95 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
96 import org.simantics.scl.compiler.internal.parsing.declarations.FieldDescription;
97 import org.simantics.scl.compiler.internal.parsing.declarations.FundepAst;
98 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
99 import org.simantics.scl.compiler.internal.parsing.types.TApplyAst;
100 import org.simantics.scl.compiler.internal.parsing.types.TEffectAst;
101 import org.simantics.scl.compiler.internal.parsing.types.TForAllAst;
102 import org.simantics.scl.compiler.internal.parsing.types.TFunctionAst;
103 import org.simantics.scl.compiler.internal.parsing.types.TListAst;
104 import org.simantics.scl.compiler.internal.parsing.types.TPredAst;
105 import org.simantics.scl.compiler.internal.parsing.types.TTupleAst;
106 import org.simantics.scl.compiler.internal.parsing.types.TVarAst;
107 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
108 import org.simantics.scl.compiler.module.ImportDeclaration;
109 import org.simantics.scl.compiler.types.Types;
110
111
112 public class SCLParserImpl extends SCLParser {
113
114     private final SCLPostLexer lexer;
115     private SCLParserOptions options;
116
117     public SCLParserImpl(Reader reader) {
118         lexer = new SCLPostLexer(reader);
119     }
120     
121     public void setParserOptions(SCLParserOptions options) {
122         this.options = options;
123         lexer.setParserOptions(options);
124     }
125     
126     public boolean isEmpty() throws Exception {
127         return lexer.peekToken().id == SCLTerminals.EOF;
128     }
129
130     @Override
131     protected Token nextToken() {
132         try {
133             Token token = lexer.nextToken();
134             /*System.out.println("TOKEN " + token.text + " (" + TERMINAL_NAMES[token.id] + ")" +
135                     " [" 
136                     + Locations.beginOf(token.location) + ".." 
137                     + Locations.endOf(token.location) + "]");*/
138             return token;
139         } catch(Exception e) {
140             if(e instanceof RuntimeException)
141                 throw (RuntimeException)e;
142             else
143                 throw new RuntimeException(e);
144         }
145     }
146
147     @Override
148     protected Object reduceDeclarations() {
149         ArrayList<DeclarationAst> declarations = new ArrayList<DeclarationAst>(length()/2);
150         for(int i=1;i<length();i+=2)
151             declarations.add((DeclarationAst)get(i));
152         return declarations;
153     }
154
155     @Override
156     protected Object reduceModule() {
157         ArrayList<DeclarationAst> declarations = new ArrayList<DeclarationAst>(length()/2+1);
158         for(int i=0;i<length();i+=2)
159             declarations.add((DeclarationAst)get(i));
160         return declarations;
161     }
162
163     @Override
164     protected Object reduceLocalTypeAnnotation() {
165         if(length() == 1)
166             return get(0);
167         return new ETypeAnnotation((Expression)get(0), (TypeAst)get(2));
168     }
169
170     @Override
171     protected Object reduceTypeAnnotation() {
172         EVar[] names = new EVar[length()/2];
173         for(int i=0;i<names.length;++i)
174             names[i] = (EVar)get(i*2);
175         return new DValueTypeAst(
176                 names,
177                 (TypeAst)get(length()-1)
178                 );
179     }
180
181     @Override
182     protected Object reduceValueDefinition() {
183         Expression rhs = (Expression)get(1);
184         return new DValueAst((Expression)get(0), rhs);
185     }
186
187     @Override
188     protected Object reduceDataDefinition() {
189         int i=2;
190         ArrayList<String> parameters = new ArrayList<String>();
191         while(i < length()) {
192             Token token = (Token)get(i++);
193             if(token.id != SCLTerminals.ID)
194                 break;
195             parameters.add(token.text);
196         }
197         ArrayList<ConstructorAst> constructors = new ArrayList<ConstructorAst>(); 
198         for(;i < length();i+=2)
199             constructors.add((ConstructorAst)get(i));
200         return new DDataAst(
201                 ((Token)get(1)).text,
202                 parameters.toArray(new String[parameters.size()]),
203                 constructors.toArray(new ConstructorAst[constructors.size()]),
204                 new String[0]
205                 );
206     }
207
208     @Override
209     protected Object reduceTypeDefinition() {
210         int i=2;
211         ArrayList<String> parameters = new ArrayList<String>();
212         while(true) {
213             Token token = (Token)get(i++);
214             if(token.id != SCLTerminals.ID)
215                 break;
216             parameters.add(token.text);
217         }
218         return new DTypeAst(
219                 ((Token)get(1)).text,
220                 parameters.toArray(new String[parameters.size()]),
221                 (TypeAst)get(i)
222                 );
223     }
224
225     @SuppressWarnings("unchecked")
226     @Override
227     protected Object reduceClassDefinition() {
228         int i=1;
229         ArrayList<TypeAst> context;
230         if(get(i) instanceof Token)
231             context = new ArrayList<TypeAst>(0);
232         else
233             context = (ArrayList<TypeAst>)get(i++);
234         String name = ((Token)get(i++)).text;
235         ArrayList<String> parameters = new ArrayList<String>();
236         while(i < length()) {
237             Token token = (Token)get(i);
238             if(token.id != SCLTerminals.ID)
239                 break;
240             parameters.add(token.text);
241             ++i;
242         }
243         ArrayList<DeclarationAst> declarations = null;
244         FundepAst[] fundeps = FundepAst.EMPTY_ARRAY;
245         while(i < length()) {
246             Token token = (Token)get(i++);
247             if(token.id == SCLTerminals.WHERE) {
248                 declarations = (ArrayList<DeclarationAst>)get(i++);
249             }
250             else if(token.id == SCLTerminals.BAR) {
251                 fundeps = (FundepAst[])get(i++);
252             }
253             else
254                 throw new InternalCompilerError();
255         }
256         return new DClassAst(context, name,
257                 parameters.toArray(new String[parameters.size()]),
258                 fundeps,
259                 declarations);
260     }
261
262     @Override
263     protected Object reduceFundep() {
264         String[] from = new String[length()-2];
265         for(int i=0;i<from.length;++i)
266             from[i] = ((Token)get(i)).text;
267         String to = ((Token)get(length()-1)).text;
268         return new FundepAst(from, to);
269     }
270
271     @Override
272     protected Object reduceFundeps() {
273         FundepAst[] fundeps = new FundepAst[(length()+1)/2];
274         for(int i=0;i<fundeps.length;++i)
275             fundeps[i] = (FundepAst)get(i*2);
276         return fundeps;
277     }
278
279     @SuppressWarnings("unchecked")
280     @Override
281     protected Object reduceInstanceDefinition() {
282         int i=1;
283         ArrayList<TypeAst> context;
284         if(get(i) instanceof Token)
285             context = new ArrayList<TypeAst>(0);
286         else
287             context = (ArrayList<TypeAst>)get(i++);
288         Token nameToken = (Token)get(i++);
289         EVar name = new EVar(nameToken.location, nameToken.text);
290         ArrayList<TypeAst> parameters = new ArrayList<TypeAst>();
291         while(i < length()) {
292             Object symbol = get(i++);
293             if(symbol instanceof Token)
294                 break;            
295             parameters.add((TypeAst)symbol);
296         }
297         ArrayList<DeclarationAst> declarations = null;
298         if(i < length())
299             declarations = (ArrayList<DeclarationAst>)get(i);
300         return new DInstanceAst(context, name,
301                 parameters.toArray(new TypeAst[parameters.size()]),
302                 declarations);
303     }
304
305     @SuppressWarnings("unchecked")
306     @Override
307     protected Object reduceDerivingInstanceDefinition() {
308         int i=2;
309         ArrayList<TypeAst> context;
310         if(get(i) instanceof Token)
311             context = new ArrayList<TypeAst>(0);
312         else
313             context = (ArrayList<TypeAst>)get(i++);
314         Token nameToken = (Token)get(i++);
315         EVar name = new EVar(nameToken.location, nameToken.text);
316         ArrayList<TypeAst> parameters = new ArrayList<TypeAst>();
317         while(i < length()) {
318             Object symbol = get(i++);
319             parameters.add((TypeAst)symbol);
320         }
321         return new DDerivingInstanceAst(context, name,
322                 parameters.toArray(new TypeAst[parameters.size()]));
323     }
324
325     @Override
326     protected Object reduceDocumentationString() {
327         return new DDocumentationAst(((Token)get(1)).text);
328     }
329
330     @Override
331     protected Object reduceAnnotation() {
332         ArrayList<Expression> parameters = new ArrayList<Expression>(length()-1);
333         for(int i=1;i<length();++i)
334             parameters.add((Expression)get(i));
335         return new DAnnotationAst((Token)get(0), parameters);
336     }
337
338     @Override
339     protected Object reducePrecedenceDefinition() {
340         EVar[] symbols = new EVar[length()/2];
341         for(int i=0;i<symbols.length;++i)
342             symbols[i] = (EVar)get(2*i + 2);
343         Associativity associativity;
344         Token token = (Token)get(0);
345         if(token.text.equals("infixl"))
346             associativity = Associativity.LEFT;
347         else if(token.text.equals("infixr"))
348             associativity = Associativity.RIGHT;
349         else
350             associativity = Associativity.NONASSOC;
351         return new DFixityAst(
352                 new Precedence(
353                         Integer.parseInt(((Token)get(1)).text), 
354                         associativity), 
355                         symbols);
356     }
357
358     @Override
359     protected Object reduceImport() {
360         // (AS ID)? importSpec?
361         int pos = 0;
362         String importKeyword = ((Token)get(pos++)).text; // (IMPORT | INCLUDE) 
363         ++pos; // BEGIN_STRING
364         String moduleName = ((Token)get(pos++)).text; // END_STRING
365         String localName = "";
366         if(pos < length()) {
367             Object temp = get(pos);
368             if(temp instanceof Token) {
369                 Token token = (Token)temp;
370                 if(token.id == SCLTerminals.AS) {
371                     ++pos; // AS
372                     localName = ((Token)get(pos++)).text; // ID
373                 }
374             }
375         }
376         ImportDeclaration.ImportSpec spec = ImportDeclaration.DEFAULT_SPEC;
377         if(pos < length())
378             spec = (ImportDeclaration.ImportSpec)get(pos++);
379         return new ImportDeclaration(moduleName, localName,
380                         importKeyword.equals("include"),
381                         spec);
382     }
383
384     @Override
385     protected Object reduceJustImport() {
386         return get(0);
387     }
388
389     @SuppressWarnings("unchecked")
390     @Override
391     protected Object reduceImportJava() {
392         return new DImportJavaAst(((Token)get(2)).text, (ArrayList<DeclarationAst>)get(4));
393     }
394
395     @Override
396     protected Object reduceEffectDefinition() {
397         return new DEffectAst(
398                 ((Token)get(1)).text,
399                 ((Token)get(3)).text,
400                 ((Token)get(5)).text);
401     }
402
403     @Override
404     protected Object reduceVarId() {
405         return new EVar(((Token)get(0)).text);
406     }
407
408     @Override
409     protected Object reduceEscapedSymbol() {
410         return new EVar(((Token)get(0)).text);
411     }
412
413     @Override
414     protected Object reduceTupleTypeConstructor() {
415         return new TVarAst(Types.tupleConstructor(length()-1).name);
416     }
417
418     @Override
419     protected Object reduceArrow() {
420         int i=length()-1;
421         TypeAst result = (TypeAst)get(i);
422         i-=2;
423         while(i >= 0) {
424             if( ((Token)get(i+1)).text.equals("=>") )
425                 result = new TPredAst((TypeAst)get(i), result);
426             else
427                 result = new TFunctionAst((TypeAst)get(i), result);
428             i-=2;
429         }
430         return result;
431     }
432
433     @Override
434     protected Object reduceBinary() {
435         if(length() == 1)
436             return get(0);
437         int i=0;
438         EVar negation = null;
439         if(get(i) instanceof Token) {
440             Token token = (Token)get(i++);
441             negation = new EVar(token.location, token.text);
442         }
443         EBinary binary = new EBinary((Expression)get(i++), negation);
444         while(i < length()) {
445             EVar operator = (EVar)get(i++);
446             Expression right = (Expression)get(i++);
447             binary.rights.add(new EBinaryRightSide(operator, right));
448         }
449         return binary;
450     }
451
452     @Override
453     protected Object reduceSimpleRhs() {
454         if(length() == 2)
455             return get(1);
456         else {
457             EBlock block = (EBlock)get(3);
458             Expression expression = (Expression)get(1);
459             block.addStatement(new GuardStatement(expression));
460             block.location = Locations.location(Locations.beginOf(expression.location), Locations.endOf(block.location));
461             return block;
462         }
463     }
464
465     private GuardedExpressionGroup reduceGuardedExpressionGroup(int length) {
466         GuardedExpression[] expressions = new GuardedExpression[length];
467         for(int i=0;i<expressions.length;++i) {
468             expressions[i] = (GuardedExpression)get(i);
469         }
470         return new GuardedExpressionGroup(expressions);
471     }
472
473     @Override
474     protected Object reduceGuardedRhs() {
475         int length = length();
476         if(length > 2 && get(length-2) instanceof Token) {
477             EBlock block = (EBlock)get(length-1);
478             block.addStatement(new GuardStatement(reduceGuardedExpressionGroup(length-2)));
479             block.location = Locations.NO_LOCATION;
480             return block;
481         }
482         else
483             return reduceGuardedExpressionGroup(length);
484     }
485
486     @Override
487     protected Object reduceStatements() {
488         EBlock block = new EBlock();
489         if(length() > 2)
490             for(int i=1;i<length();i+=2)
491                 block.addStatement((Statement)get(i));
492         return block;
493     }
494
495     @Override
496     protected Object reduceConstructor() {
497         int idPos;
498         for(idPos=0;idPos<length();idPos+=2)
499             if(((Token)get(idPos)).id == SCLTerminals.ID)
500                 break;
501         DAnnotationAst[] annotations = idPos == 0 ? DAnnotationAst.EMPTY_ARRAY : new DAnnotationAst[idPos/2];
502         for(int i=0;i<idPos/2;++i)
503             annotations[i] = new DAnnotationAst((Token)get(i*2), 
504                     Arrays.asList((Expression)get(i*2+1)));
505         TypeAst[] parameters = new TypeAst[length()-idPos-1];
506         for(int i=0;i<parameters.length;++i)
507             parameters[i] = (TypeAst)get(i+idPos+1);
508         return new ConstructorAst(annotations, ((Token)get(idPos)).text, parameters, null);
509     }
510
511     @Override
512     protected Object reduceContext() {
513         ArrayList<TypeAst> result = new ArrayList<TypeAst>(length()/2-1);
514         for(int i=1;i<length()-2;i+=2)
515             result.add((TypeAst)get(i));
516         return result;
517     }
518
519     @Override
520     protected Object reduceTypeVar() {
521         return new TVarAst(((Token)get(0)).text);
522     }
523
524     @Override
525     protected Object reduceTupleType() {
526         if(length() == 2)
527             return new TTupleAst(TypeAst.EMPTY_ARRAY);
528         if(length() == 3) {
529             Symbol sym = (Symbol)get(1);
530             sym.location = Locations.NO_LOCATION;
531             return sym;
532         }
533         int dim = length()/2;
534         TypeAst[] parameters = new TypeAst[dim];
535         for(int i=0;i<dim;++i)
536             parameters[i] = (TypeAst)get(i*2+1);
537         return new TTupleAst(parameters);
538     }
539
540     @Override
541     protected Object reduceListType() {
542         return new TListAst((TypeAst)get(1));
543     }
544
545     @Override
546     protected Object reduceListTypeConstructor() {
547         return new TVarAst("[]");
548     }
549
550     @Override
551     protected Object reduceTupleConstructor() {
552         return new EVar(Types.tupleConstructor(length()-1).name);
553     }
554
555     @Override
556     protected Object reduceVar() {
557         return get(0);
558     }
559
560     @Override
561     protected Object reduceBlank() {
562         return new EVar("_");
563     }
564
565     @Override
566     protected Object reduceInteger() {
567         return new EIntegerLiteral(((Token)get(0)).text);
568     }
569
570     @Override
571     protected Object reduceFloat() {
572         return new ERealLiteral(((Token)get(0)).text);
573     }
574
575     @Override
576     protected Object reduceString() {
577         return get(0);
578     }
579
580     @Override
581     protected Object reduceChar() {
582         String text = ((Token)get(0)).text;
583         char c = text.charAt(text.length()-2);
584         if(text.length() == 4) {
585             switch(c) {
586             case 'n': c = '\n'; break;
587             case 't': c = '\t'; break;
588             case 'b': c = '\b'; break;
589             case 'f': c = '\f'; break;
590             case 'r': c = '\r'; break;
591             }
592         }
593         return new ELiteral(new CharacterConstant(c));
594     }
595
596     @Override
597     protected Object reduceTuple() {
598         if(length() == 2)
599             return new EConstant(Builtins.TUPLE_CONSTRUCTORS[0]);
600         if(length() == 3) {
601             Symbol sym = (Symbol)get(1);
602             sym.location = Locations.NO_LOCATION;
603             return sym;
604         }
605         int dim = length()/2;
606         Expression[] parameters = new Expression[dim];
607         for(int i=0;i<dim;++i)
608             parameters[i] = (Expression)get(i*2+1);
609         EConstant tupleConstructor = new EConstant(Builtins.TUPLE_CONSTRUCTORS[dim]);
610         tupleConstructor.location = Locations.location(
611                 Locations.beginOf(((Token)get(0)).location),
612                 Locations.endOf(((Token)get(length()-1)).location));
613         return new EApply(tupleConstructor, parameters);
614     }
615
616     public static Expression rightSection(EVar op, Expression e) {
617         long loc = Locations.combine(op.location, e.location);
618         Variable var = new Variable("rightSectionTemp");
619         return new ESimpleLambda(loc, var, 
620                 new EApply(loc, op, new EVariable(loc, var), e));
621     }
622
623     @Override
624     protected Object reduceRightSection() {
625         Variable var = new Variable("rightSectionTemp");
626         long loc = Locations.combine(((Token)get(0)).location, ((Token)get(length()-1)).location);
627         EVar symbol = (EVar)get(1);
628         return new ESimpleLambda(var, 
629                 new EApply(loc, symbol,
630                         new EVariable(loc, var), (Expression)get(2)));
631     }
632
633     @Override
634     protected Object reduceLeftSection() {
635         return new EApply((EVar)get(2), (Expression)get(1));
636     }
637
638     @Override
639     protected Object reduceListLiteral() {
640         if(length() == 2)
641             return new EListLiteral(Expression.EMPTY_ARRAY);
642         int dim = length()/2;
643         Expression[] components = new Expression[dim];
644         for(int i=0;i<dim;++i)
645             components[i] = (Expression)get(i*2+1);
646         return new EListLiteral(components);
647     }
648
649     @Override
650     protected Object reduceRange() {
651         return new ERange(
652                 (Expression)get(1),
653                 (Expression)get(3)
654                 );
655     }
656
657     @Override
658     protected Object reduceListComprehension() {
659         ListQualifier qualifier = (ListQualifier)get(3);
660         for(int i=5;i<length();i+=2) {
661             ListQualifier right = (ListQualifier)get(i);
662             if(right instanceof ListThen) {
663                 ((ListThen) right).setLeft(qualifier);
664                 qualifier = right;
665             }
666             else
667                 qualifier = new ListSeq(qualifier, right);
668         }
669         return new EListComprehension((Expression)get(1), qualifier);
670     }
671
672     @Override
673     protected Object reduceAs() {
674         Token id = (Token)get(0);
675         return new EAsPattern(new EVar(id.location, id.text), (Expression)get(2));
676     }
677
678     @Override
679     protected Object reduceGuardedExpEq() {
680         Expression[] guards = new Expression[length()/2-1];
681         for(int i=0;i<guards.length;++i)
682             guards[i] = (Expression)get(i*2+1);
683         return new GuardedExpression(guards, (Expression)get(length()-1));
684     }
685
686     @Override
687     protected Object reduceLambda() {
688         Expression[] patterns = new Expression[length()-3];
689         for(int i=0;i<patterns.length;++i)
690             patterns[i] = (Expression)get(i+1);
691         Case case_ = new Case(patterns, (Expression)get(length()-1));
692         case_.setLhs(Locations.combine(patterns[0].location, patterns[patterns.length-1].location));
693         return new ELambda(case_);
694     }
695     
696     @Override
697     protected Object reduceLambdaMatch() {
698         Case[] cases = new Case[length()/2-1];
699         for(int i=0;i<cases.length;++i)
700             cases[i] = (Case)get(i*2+2);
701         return new ELambda(cases);
702     }
703
704     @Override
705     protected Object reduceLet() {
706         EBlock block = (EBlock)get(1);
707         Expression expression = (Expression)get(3);
708         block.addStatement(new GuardStatement(expression));
709         Token letToken = (Token)get(0);
710         block.location = Locations.location(
711                 Locations.beginOf(letToken.location),
712                 Locations.endOf(expression.location));
713         return block;
714     }
715
716     @Override
717     protected Object reduceIf() {
718         return new EIf(
719                 (Expression)get(1),
720                 (Expression)get(3),
721                 length() == 6 ? (Expression)get(5) : null);
722     }
723
724     @Override
725     protected Object reduceMatch() {
726         Case[] cases = new Case[length()/2-2];
727         for(int i=0;i<cases.length;++i)
728             cases[i] = (Case)get(i*2+4);
729         return new EMatch((Expression)get(1), cases);
730     }
731
732     @Override
733     protected Object reduceDo() {
734         EBlock block = (EBlock)get(1);
735         Token doToken = (Token)get(0);
736         block.setMonadic( doToken.text.equals("mdo") );
737         block.location = Locations.location(Locations.beginOf(doToken.location), Locations.endOf(block.location));
738         return block;
739     }
740
741     @Override
742     protected Object reduceSelect() {
743         return new ESelect(((Token)get(0)).id, (Expression)get(1), new QConjunction((Query[])get(3)));
744     }
745        
746     @Override
747     protected Object reduceEnforce() {
748         return new EEnforce(new QConjunction((Query[])get(1)));
749     }
750
751     @Override
752     protected Object reduceApply() {
753         if(length() == 1)
754             return get(0);
755         Expression[] parameters = new Expression[length()-1];
756         for(int i=0;i<parameters.length;++i)
757             parameters[i] = (Expression)get(i+1);
758         return new EApply((Expression)get(0), parameters);
759     }
760
761     @Override
762     protected Object reduceSymbol() {
763         return new EVar(((Token)get(0)).text);
764     }
765
766     @Override
767     protected Object reduceEscapedId() {
768         return new EVar(((Token)get(0)).text);
769     }
770
771     @Override
772     protected Object reduceMinus() {
773         return new EVar(((Token)get(0)).text);
774     }
775
776     @Override
777     protected Object reduceLess() {
778         return new EVar(((Token)get(0)).text);
779     }
780
781     @Override
782     protected Object reduceGreater() {
783         return new EVar(((Token)get(0)).text);
784     }
785
786     @Override
787     protected Object reduceDot() {
788         return new EVar(((Token)get(0)).text);
789     }
790
791     @Override
792     protected Object reduceCase() {
793         return new Case((Expression)get(0), (Expression)get(1));
794     }
795
796     @Override
797     protected Object reduceGuardQualifier() {
798         return new ListGuard((Expression)get(0));
799     }
800
801     @Override
802     protected Object reduceLetQualifier() {
803         return new ListAssignment((Expression)get(0), (Expression)get(2));
804     }
805
806     @Override
807     protected Object reduceBindQualifier() {
808         return new ListGenerator((Expression)get(0), (Expression)get(2));
809     }
810
811     @Override
812     protected Object reduceThenQualifier() {
813         return new ListThen((Expression)get(1), length()==4 ? (Expression)get(3) : null);
814     }
815
816     @Override
817     protected Object reduceGuardStatement() {
818         return new GuardStatement((Expression)get(0));
819     }
820
821     @Override
822     protected Object reduceLetStatement() {
823         return new LetStatement((Expression)get(0), (Expression)get(1));
824     }
825
826     @Override
827     protected Object reduceBindStatement() {
828         return new BindStatement((Expression)get(0), (Expression)get(2));
829     }
830
831     @Override
832     protected Object reduceSimpleCaseRhs() {
833         return get(1);
834     }
835
836     @Override
837     protected Object reduceGuardedCaseRhs() {
838         GuardedExpression[] expressions = new GuardedExpression[length()];
839         for(int i=0;i<expressions.length;++i)
840             expressions[i] = (GuardedExpression)get(i);
841         return new GuardedExpressionGroup(expressions);
842     }
843
844     @Override
845     protected Object reduceGuardedExpArrow() {
846         Expression[] guards = new Expression[length()/2-1];
847         for(int i=0;i<guards.length;++i)
848             guards[i] = (Expression)get(i*2+1);
849         return new GuardedExpression(guards, (Expression)get(length()-1));
850     }
851
852     @Override
853     protected Object reduceEffect() {
854         ArrayList<TypeAst> effects = new ArrayList<TypeAst>(length()/2-1);
855         for(int i=1;i<length()-1;i+=2) {
856             Token token = (Token)get(i);
857             TVarAst ast = new TVarAst(token.text);
858             ast.location = token.location;
859             effects.add(ast);
860         }
861         return new TEffectAst(effects, (TypeAst)get(length()-1));
862     }
863
864     @Override
865     protected Object reduceJustEtype() {
866         return get(0);
867     }
868
869     @Override
870     protected Object reduceForAll() {
871         String[] vars = new String[length()-3];
872         for(int i=0;i<vars.length;++i)
873             vars[i] = ((Token)get(i+1)).text;
874         return new TForAllAst(vars, (TypeAst)get(length()-1));
875     }
876
877     @Override
878     protected Object reduceApplyType() {
879         TypeAst[] parameters = new TypeAst[length()-1];
880         for(int i=0;i<parameters.length;++i)
881             parameters[i] = (TypeAst)get(i+1);
882         return new TApplyAst((TypeAst)get(0), parameters);
883     }
884
885     @SuppressWarnings("unchecked")
886     @Override
887     protected void postReduce(Object reduced) {
888         if(!(reduced instanceof Symbol))
889             return;
890         Symbol sym = (Symbol)reduced;
891         if(sym.location != Locations.NO_LOCATION || length() == 0)
892             return;
893         Object first = get(0);
894         if(!(first instanceof Symbol)) {
895             if(first instanceof List) {
896                 List<Object> ll = (List<Object>)first;
897                 first = ll.get(0);
898             }
899             else {
900                 Object[] ll = (Object[])first;
901                 if(ll.length > 0)
902                     first = ll[0];
903                 else
904                     first = get(1);
905             }
906         }
907         Object last = get(length()-1);
908         if(!(last instanceof Symbol)) {
909             if(last instanceof List) {
910                 List<Object> ll = (List<Object>)last;
911                 last = ll.get(ll.size()-1);
912             }
913             else {
914                 Object[] ll = (Object[])last;
915                 if(ll.length > 0)
916                     last = ll[ll.length-1];
917                 else
918                     last = get(length()-2);
919             }
920         }
921         sym.location = (((Symbol)first).location & 0xffffffff00000000L) 
922                 | (((Symbol)last).location & 0xffffffffL);
923         /*for(int i=0;i<length();++i) {
924             Object obj = get(i);
925             System.out.print(obj.getClass().getSimpleName());
926             if(obj instanceof Token) {
927                 Token t = (Token)obj;
928                 System.out.print("(" + t.text + ")");
929             }
930             if(obj instanceof Symbol) {
931                 Symbol s = (Symbol)obj;
932                 System.out.print("["+ Locations.beginOf(s.location) + "-" + Locations.endOf(s.location) + "]");
933             }
934             System.out.print(" ");
935         }
936         System.out.println("-> " + reduced.getClass().getSimpleName() + " " +
937                 Locations.beginOf(sym.location) + "-" + Locations.endOf(sym.location));*/
938     }
939
940     @Override
941     protected RuntimeException syntaxError(Token token, String description) {
942         throw new SCLSyntaxErrorException(token.location, description);
943     }
944
945     @Override
946     protected Object reduceIdAccessor() {
947         return new IdAccessor(((Token)get(0)).text);
948     }
949
950     @Override
951     protected Object reduceStringAccessor() {
952         return new StringAccessor(((Token)get(1)).text);
953     }
954
955     @Override
956     protected Object reduceExpAccessor() {
957         return new ExpressionAccessor((Expression)get(1));
958     }
959
960     @Override
961     protected Object reduceFieldAccess() {
962         if(length() == 1)
963             return get(0);
964         FieldAccessor[] accessors = new FieldAccessor[length()/2];
965         for(int i=0;i<accessors.length;++i) {
966             FieldAccessor accessor = (FieldAccessor)get(i*2+2);
967             accessor.accessSeparator = ((Token)get(i*2+1)).text.charAt(0);
968             accessors[i] = accessor;
969         }
970         return new EFieldAccess((Expression)get(0), accessors);
971     }
972
973     @Override
974     protected Object reduceQueryBlock() {
975         if(length() == 2)
976             return Query.EMPTY_ARRAY;
977         Query[] queries = new Query[length()/2];
978         for(int i=0;i<queries.length;++i)
979             queries[i] = (Query)get(2*i+1);
980         return queries;
981     }
982
983     @Override
984     protected Object reduceGuardQuery() {
985         return new QPreGuard((Expression)get(0));
986     }
987
988     @Override
989     protected Object reduceEqualsQuery() {
990         return new QPreEquals((Expression)get(0), (Expression)get(2));
991     }
992
993     @Override
994     protected Object reduceBindQuery() {
995         return new QPreBinds((Expression)get(0), (Expression)get(2));
996     }
997
998     @Override
999     protected Object reduceCompositeQuery() {
1000         Query[] queries = (Query[])get(1);
1001         switch(((Token)get(0)).text.charAt(1)) {
1002         case '&': return new QConjunction(queries);
1003         case '|': return new QDisjunction(queries);
1004         case '!': return new QNegation(new QConjunction(queries));
1005         case '?': return new QAlternative(queries);
1006         default: throw new InternalCompilerError();
1007         }
1008     }
1009     
1010     @Override
1011     protected Object reduceRuleStatement() {
1012         return new RuleStatement((Expression)get(0), new QConjunction((Query[])get(2)));
1013     }
1014     
1015     @Override
1016     protected Object reduceEntityTypeAnnotation() {
1017         return new EEntityTypeAnnotation((Expression)get(0), (Token)get(2), 
1018                 length() > 3 
1019                 ? new QConjunction((Query[])get(length()-1))
1020                 : null);
1021     }
1022
1023     @Override
1024     protected Object reduceHashedId() {
1025         return new EVar("#" + ((Token)get(1)).text);
1026     }
1027
1028     @Override
1029     protected Object reduceStringLiteral() {
1030         int expCount = length()/3;
1031         if(expCount == 0)
1032             return new ELiteral(new StringConstant(((Token)get(1)).text));
1033         else {
1034             String[] strings = new String[expCount+1];
1035             Expression[] expressions = new Expression[expCount];
1036             for(int i=0;i<expCount;++i) {
1037                 strings[i] = ((Token)get(i*3+1)).text;
1038                 expressions[i] = (Expression)get(i*3+2);
1039             }
1040             strings[expCount] = ((Token)get(expCount*3+1)).text;
1041             return new EStringLiteral(strings, expressions);
1042         }
1043     }
1044
1045     @Override
1046     protected Object reduceOneCommand() {
1047         return null;
1048     }
1049     
1050     @Override
1051     protected Object reduceManyCommands() {
1052         return null;
1053     }
1054
1055     @Override
1056     protected Object reduceStatementCommand() {
1057         // to be extended in subclasses
1058         return null;
1059     }
1060
1061     @Override
1062     protected Object reduceImportCommand() {
1063         // to be extended in subclasses
1064         return null;
1065     }
1066     
1067     @Override
1068     protected Object reduceImportValueItem() {
1069         return new EVar(((Token)get(0)).text);
1070     }
1071     
1072     @Override
1073     protected Object reduceImportHiding() {
1074         EVar[] values = new EVar[(length()-2)/2];
1075         for(int i=0;i<values.length;++i)
1076             values[i] = (EVar)get(i*2+2);
1077         return new ImportDeclaration.ImportSpec(true, values);
1078     }
1079     
1080     @Override
1081     protected Object reduceImportShowing() {
1082         EVar[] values = new EVar[(length()-1)/2];
1083         for(int i=0;i<values.length;++i)
1084             values[i] = (EVar)get(i*2+1);
1085         return new ImportDeclaration.ImportSpec(false, values);
1086     }
1087
1088     @Override
1089     protected Object reduceRuleDeclarations() {
1090         ArrayList<Object> declarations = new ArrayList<Object>(length()/2);
1091         for(int i=1;i<length();i+=2)
1092             declarations.add((Object)get(i));
1093         return declarations;
1094     }
1095
1096     private static final String[] EMPTY_STRING_ARRAY = new String[0];
1097     
1098     @SuppressWarnings("unchecked")
1099     @Override
1100     protected Object reduceRuleDefinition() {
1101         String[] extendsNames = EMPTY_STRING_ARRAY;
1102         if(length() >= 6) {
1103             int extendsCount = (length() - 4) / 2;
1104             extendsNames = new String[extendsCount]; 
1105             for(int i=0;i<extendsCount;++i)
1106                 extendsNames[i] = ((Token)get(3+i*2)).text;
1107         }
1108         
1109         DRuleAst rule = new DRuleAst(
1110                 ((Token)get(0)).id == SCLTerminals.ABSTRACT_RULE,
1111                 ((Token)get(1)).text,
1112                 extendsNames);
1113         
1114         ArrayList<Object> ruleDeclarations = (ArrayList<Object>)get(length()-1);
1115         ArrayList<Query> section = null;
1116         for(Object decl : ruleDeclarations) {
1117             if(decl instanceof DAnnotationAst) {
1118                 DAnnotationAst annotation = (DAnnotationAst)decl;
1119                 section = rule.getSection(annotation.id.text.substring(1));
1120             }
1121             else if(decl instanceof Query) {
1122                 if(section == null)
1123                     section = rule.getSection("when");
1124                 section.add((Query)decl);
1125             }
1126             else
1127                 throw new InternalCompilerError();
1128         }
1129         return rule;
1130     }
1131
1132     @Override
1133     protected Object reduceQueryRuleDeclaration() {
1134         return get(0);
1135     }
1136
1137     @Override
1138     protected Object reduceMappingRelationDefinition() {
1139         TypeAst[] types = new TypeAst[length()-2];
1140         for(int i=0;i<types.length;++i)
1141             types[i] = (TypeAst)get(i+2);
1142         return new DMappingRelationAst(
1143                 ((Token)get(1)).text,
1144                 types);
1145     }
1146
1147     @Override
1148     protected Object reduceTransformation() {
1149         return new ETransformation(
1150                 ((Token)get(1)).text,
1151                 new QConjunction((Query[])get(3))
1152                 );
1153     }
1154
1155     @SuppressWarnings("unchecked")
1156     @Override
1157     protected Object reduceRelationDefinition() {
1158         return new DRelationAst((Expression)get(0), 
1159                 ((ArrayList<Object>)get(2)).toArray());
1160     }
1161
1162     @Override
1163     protected Object reduceRecord() {
1164         FieldAssignment[] fields = new FieldAssignment[length()/2-1];
1165         for(int i=0;i<fields.length;++i)
1166             fields[i] = (FieldAssignment)get(2+i*2);
1167         return new ERecord((Token)get(0), fields);
1168     }
1169
1170     @Override
1171     protected Object reduceField() {
1172         return new FieldAssignment(((Token)get(0)).text, (Expression)get(2));
1173     }
1174     
1175     @Override
1176     protected Object reduceFieldShorthand() {
1177         return new FieldAssignment(((Token)get(0)).text, null);
1178     }
1179
1180     @Override
1181     protected Object reduceRecordConstructor() {
1182         int idPos;
1183         for(idPos=0;idPos<length();idPos+=2)
1184             if(((Token)get(idPos)).id == SCLTerminals.ID)
1185                 break;
1186         DAnnotationAst[] annotations = idPos == 0 ? DAnnotationAst.EMPTY_ARRAY : new DAnnotationAst[idPos/2];
1187         for(int i=0;i<idPos/2;++i)
1188             annotations[i] = new DAnnotationAst((Token)get(i*2), 
1189                     Arrays.asList((Expression)get(i*2+1)));
1190         TypeAst[] parameters = new TypeAst[(length()-idPos-1)/2];
1191         String[] fieldNames = new String[parameters.length];
1192         for(int i=0;i<parameters.length;++i) {
1193             FieldDescription fieldDesc = (FieldDescription)get(idPos+(i+1)*2);
1194             parameters[i] = fieldDesc.type;
1195             fieldNames[i] = fieldDesc.name;
1196         }
1197         return new ConstructorAst(annotations, ((Token)get(idPos)).text, parameters, fieldNames);
1198     }
1199
1200     @Override
1201     protected Object reduceFieldDescription() {
1202         return new FieldDescription(((Token)get(0)).text, (TypeAst)get(2));
1203     }
1204
1205     @Override
1206     protected Object reduceEq() {
1207         return (Expression)get(2);
1208     }
1209
1210     @Override
1211     protected Object reduceEquationBlock() {
1212         if(length() == 0)
1213             return new EEquations(Equation.EMPTY_ARRAY);
1214         Equation[] equations = new Equation[length()/2+1];
1215         for(int i=0;i<equations.length;++i)
1216             equations[i] = (Equation)get(2*i);
1217         return new EEquations(equations);
1218     }
1219
1220     @Override
1221     protected Object reduceGuardEquation() {
1222         return new EqGuard((Expression)get(0));
1223     }
1224
1225     @Override
1226     protected Object reduceBasicEquation() {
1227         return new EqBasic((Expression)get(0), (Expression)get(2));
1228     }
1229
1230     @Override
1231     protected Object reduceViewPattern() {
1232         return new EViewPattern((Expression)get(1), (Expression)get(3));
1233     }
1234
1235     @Override
1236     protected Object reduceCHRStatement() {
1237         return new CHRStatement((ListQualifier[])get(0), (ListQualifier[])get(2));
1238     }
1239
1240     @Override
1241     protected Object reduceConstraintStatement() {
1242         TypeAst[] parameterTypes = new TypeAst[length()-2];
1243         for(int i=0;i<parameterTypes.length;++i)
1244             parameterTypes[i] = (TypeAst)get(2+i);
1245         return new ConstraintStatement((Token)get(1), parameterTypes);
1246     }
1247
1248     @Override
1249     protected Object reduceCHRQuery() {
1250         ListQualifier[] query = new ListQualifier[(length()+1)/2];
1251         for(int i=0;i<query.length;++i)
1252             query[i] = (ListQualifier)get(i*2);
1253         return query;
1254     }
1255
1256     /*
1257     @Override
1258     protected Object reduceWhen() {
1259         return new EWhen(
1260                 new QConjunction((Query[])get(1)),
1261                 (Expression)get(3));
1262     }*/
1263     
1264     @Override
1265     protected Object reduceVerboseCHRQuery() {
1266         ListQualifier[] query = new ListQualifier[(length()-1)/2];
1267         for(int i=0;i<query.length;++i)
1268             query[i] = (ListQualifier)get(i*2+1);
1269         return query;
1270     }
1271     
1272     @Override
1273     protected Object reduceVerboseCHRStatement() {
1274         return new CHRStatement((ListQualifier[])get(1), (ListQualifier[])get(3));
1275     }
1276
1277     @Override
1278     protected Object reduceDummy() {
1279         throw new UnsupportedOperationException();
1280     }
1281
1282 }