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