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