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