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