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