Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / parser / ooaCustomParser.java @ 10

1
/**
2
  *
3
  *                      OOAS Compiler
4
  *
5
  *       Copyright 2015, AIT Austrian Institute of Technology.
6
  * This code is based on the C# Version of the OOAS Compiler, which is
7
  * copyright 2015 by the Institute of Software Technology, Graz University
8
  * of Technology with portions copyright by the AIT Austrian Institute of
9
  * Technology. All rights reserved.
10
  *
11
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
12
  *
13
  * If you modify the file please update the list of contributors below to in-
14
  * clude your name. Please also stick to the coding convention of using TABs
15
  * to do the basic (block-level) indentation and spaces for anything after
16
  * that. (Enable the display of special chars and it should be pretty obvious
17
  * what this means.) Also, remove all trailing whitespace.
18
  *
19
  * Contributors:
20
  *               Willibald Krenn (AIT)
21
  *               Stephan Zimmerer (AIT)
22
  *               Markus Demetz (AIT)
23
  *               Christoph Czurda (AIT)
24
  *
25
  */
26

    
27

    
28
package org.momut.ooas.parser;
29

    
30
import java.util.LinkedHashMap;
31
import java.util.LinkedList;
32
import java.util.List;
33

    
34
import org.antlr.runtime.MismatchedTokenException;
35
import org.antlr.runtime.Parser;
36
import org.antlr.runtime.RecognitionException;
37
import org.antlr.runtime.RecognizerSharedState;
38
import org.antlr.runtime.Token;
39
import org.antlr.runtime.TokenStream;
40
import org.momut.ooas.ast.IScope;
41
import org.momut.ooas.ast.expressions.AccessExpression;
42
import org.momut.ooas.ast.expressions.BinaryOperator;
43
import org.momut.ooas.ast.expressions.CallExpression;
44
import org.momut.ooas.ast.expressions.ExistsQuantifier;
45
import org.momut.ooas.ast.expressions.Expression;
46
import org.momut.ooas.ast.expressions.ExpressionKind;
47
import org.momut.ooas.ast.expressions.ForallQuantifier;
48
import org.momut.ooas.ast.expressions.IdentifierExpression;
49
import org.momut.ooas.ast.expressions.LeafExpression;
50
import org.momut.ooas.ast.expressions.ListConstructor;
51
import org.momut.ooas.ast.expressions.MapConstructor;
52
import org.momut.ooas.ast.expressions.ObjectConstructor;
53
import org.momut.ooas.ast.expressions.Quantifier;
54
import org.momut.ooas.ast.expressions.SetConstructor;
55
import org.momut.ooas.ast.expressions.TernaryOperator;
56
import org.momut.ooas.ast.expressions.TupleConstructor;
57
import org.momut.ooas.ast.expressions.TupleMapAccessExpression;
58
import org.momut.ooas.ast.expressions.UnaryOperator;
59
import org.momut.ooas.ast.expressions.UnresolvedIdentifierExpression;
60
import org.momut.ooas.ast.expressions.ValueExpression;
61
import org.momut.ooas.ast.identifiers.AttributeIdentifier;
62
import org.momut.ooas.ast.identifiers.ConstantIdentifier;
63
import org.momut.ooas.ast.identifiers.EnumIdentifier;
64
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier;
65
import org.momut.ooas.ast.identifiers.FunctionIdentifier;
66
import org.momut.ooas.ast.identifiers.Identifier;
67
import org.momut.ooas.ast.identifiers.IdentifierKind;
68
import org.momut.ooas.ast.identifiers.IdentifierList;
69
import org.momut.ooas.ast.identifiers.LocalVariableIdentifier;
70
import org.momut.ooas.ast.identifiers.MainModule;
71
import org.momut.ooas.ast.identifiers.MethodIdentifier;
72
import org.momut.ooas.ast.identifiers.NamedActionIdentifier;
73
import org.momut.ooas.ast.identifiers.ParameterIdentifier;
74
import org.momut.ooas.ast.identifiers.SelfTypeIdentifier;
75
import org.momut.ooas.ast.identifiers.TypeIdentifier;
76
import org.momut.ooas.ast.statements.AbortStatement;
77
import org.momut.ooas.ast.statements.Assignment;
78
import org.momut.ooas.ast.statements.Block;
79
import org.momut.ooas.ast.statements.BreakStatement;
80
import org.momut.ooas.ast.statements.Call;
81
import org.momut.ooas.ast.statements.GuardedCommand;
82
import org.momut.ooas.ast.statements.KillStatement;
83
import org.momut.ooas.ast.statements.NondetBlock;
84
import org.momut.ooas.ast.statements.PrioBlock;
85
import org.momut.ooas.ast.statements.SeqBlock;
86
import org.momut.ooas.ast.statements.SkipStatement;
87
import org.momut.ooas.ast.statements.Statement;
88
import org.momut.ooas.ast.types.BoolType;
89
import org.momut.ooas.ast.types.CharType;
90
import org.momut.ooas.ast.types.EnumType;
91
import org.momut.ooas.ast.types.FloatType;
92
import org.momut.ooas.ast.types.FunctionType;
93
import org.momut.ooas.ast.types.IntType;
94
import org.momut.ooas.ast.types.ListType;
95
import org.momut.ooas.ast.types.MapType;
96
import org.momut.ooas.ast.types.OoActionSystemType;
97
import org.momut.ooas.ast.types.OpaqueType;
98
import org.momut.ooas.ast.types.TupleType;
99
import org.momut.ooas.ast.types.TypeKind;
100
import org.momut.ooas.ast.types.Type;
101
import org.momut.ooas.ast.types.ValuedEnumType;
102
import org.momut.ooas.ast.types.FunctionType.FunctionTypeEnum;
103
import org.momut.ooas.utils.exceptions.ArgumentException;
104
import org.momut.ooas.utils.exceptions.NotImplementedException;
105
import org.momut.ooas.visitors.OoaResolveExpressionsVisitor;
106

    
107
public class ooaCustomParser extends Parser
108
{
109
        public ParserState pState;
110

    
111

    
112
        public boolean IsRightToLeft(ExpressionKind type)
113
        {
114
                return type == ExpressionKind.implies; // implication has right grouping
115
        }
116

    
117
        public int GetOperatorPrecedence(ExpressionKind type)
118
        {
119
                switch (type)
120
                {
121
                /*Family of Evaluators*/
122

    
123
                case abs:    // T_ABS:
124
                case card:   // T_CARD:
125
                case dom:    // T_DOM:
126
                case range:  // T_RNG:
127
                case merge:  // T_MERGE:
128
                case len:    // T_LEN:
129
                case elems:  // T_ELEMS:
130
                case head:   // T_HEAD:
131
                case tail:   // T_TAIL:
132
                case conc:   // T_CONC:
133
                case inds:   // T_INDS:
134
                case dinter: // T_DINTER:
135
                case dunion: // T_DUNION:
136
                        return 1;
137

    
138
                case domresby:   // T_DOMRESBY:
139
                case domresto:   // T_DOMRESTO:
140
                case rngresby:   // T_RNGRESBY:
141
                case rngresto:   // T_RNGRESTO:
142
                        return 2;
143

    
144
                case div:    // T_DIV:
145
                case idiv:   // T_IDIV:
146
                case mod:    // T_MOD:
147
                case prod:   // T_PROD:
148
                case inter:  // T_INTER:
149
                        return 3;
150

    
151
                case sum:    // T_SUM:
152
                case minus:  // T_MINUS:
153
                case union:  // T_UNION:
154
                case diff:   // T_DIFF:
155
                case munion: // T_MUNION:
156
                case seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
157
                        return 4;
158

    
159
                        /*Family of Relations*/
160

    
161
                case less:
162
                case lessequal:
163
                case greater:
164
                case greaterequal:
165
                case equal:
166
                case notequal:
167
                case subset:
168
                case elemin:
169
                case notelemin:
170
                        return 5;
171

    
172
                        /*Family of Connectives*/
173

    
174
                case and:    // T_AND:
175
                        return 6;
176

    
177
                case or:     // T_OR:
178
                        return 7;
179

    
180
                case implies:    // T_IMPLIES:
181
                        return 8;
182

    
183
                case biimplies:  // T_BIIMPLIES:
184
                        return 9;
185

    
186
                default:
187
                        throw new NotImplementedException("operator not supported: " + type.toString());
188
                        // return 0;
189
                }
190
        }
191

    
192
        /*taken from antlr homepage:
193
     http://www.antlr.org/wiki/display/ANTLR3/Operator+precedence+parser
194
         */
195
        int findPivot(List<BinaryOperator> operators, int startIndex, int stopIndex)
196
        {
197
                int pivot = startIndex;
198
                final BinaryOperator binop = operators.get(pivot);
199
                int pivotRank = GetOperatorPrecedence(binop.kind());
200
                for (int i = startIndex + 1; i <= stopIndex; i++)
201
                {
202
                        final ExpressionKind type = operators.get(i).kind();
203
                        final int current = GetOperatorPrecedence(type);
204
                        final boolean rtl = IsRightToLeft(type);
205
                        if (current > pivotRank || (current == pivotRank && rtl))
206
                        {
207
                                pivot = i;
208
                                pivotRank = current;
209
                        }
210
                }
211
                return pivot;
212
        }
213

    
214
        Expression createPrecedenceTree(
215
                        List<Expression> expressions,
216
                        List<BinaryOperator> operators,
217
                        int startIndex,
218
                        int stopIndex)
219
        {
220
                if (stopIndex == startIndex)
221
                        return expressions.get(startIndex);
222

    
223
                final int pivot = findPivot(operators, startIndex, stopIndex - 1);
224

    
225
                final BinaryOperator result = operators.get(pivot);
226
                result.SetLeftChild(createPrecedenceTree(expressions, operators, startIndex, pivot));
227
                result.SetRightChild(createPrecedenceTree(expressions, operators, pivot + 1, stopIndex));
228
                return result;
229
        }
230

    
231
        Expression createPrecedenceTree(List<Expression> expressions, List<BinaryOperator> operators)
232
        {
233
                return createPrecedenceTree(expressions, operators, 0, expressions.size() - 1);
234
        }
235

    
236

    
237
        /* add error message to state. */
238
        private void doError(Token aToken, String aMessage)
239
        {
240
                pState.AddErrorMessage(
241
                                new ParserError(pState.filename, aToken, aMessage));
242
        }
243

    
244
//        /* add warning message to state */
245
//        private void doWarning(Token id1, String p)
246
//        {
247
//                pState.AddWarningMessage(new ParserWarning(pState.filename, id1, p));
248
//        }
249

    
250
        private void doError(String aMessage)
251
        {
252
                pState.AddErrorMessage(
253
                                new ParserError(pState.filename, 0, 0, aMessage));
254
        }
255

    
256
        /* init global state */
257
         void initializeTopLevelParserState()
258
        {
259
                pState.ooaSystem = new MainModule();
260
                pState.PushResolveStack(pState.ooaSystem);
261
        }
262

    
263

    
264
        private IScope GetScope()
265
        {
266
                return pState.currentScope;
267
        }
268

    
269

    
270
        /*create a named constant*/
271
         void addNamedConst(Token aName, Expression anExpr)
272
        {
273
                if (pState.currentScope.ResolveIdentifier(aName.getText()) == null)
274
                {
275
                        /* needs to be a constant... */
276
                        final ConstantIdentifier aConst = new ConstantIdentifier(aName, anExpr, GetScope());
277

    
278
                        final OoaResolveExpressionsVisitor resolver = new OoaResolveExpressionsVisitor(pState);
279
                        aConst.Accept(resolver);
280

    
281
                        if (aConst.Value() == null || aConst.Value().type() == null || aConst.Value().kind() != ExpressionKind.Value)
282
                        {
283
                                doError(aName, String.format("%s not a constant!", aName.getText()));
284
                        }
285
                        else
286
                        {
287
                                aConst.SetType(aConst.Value().type());
288
                                pState.currentScope.AddIdentifier(aConst, null);
289
                        }
290
                }
291
                else
292
                        doError(aName, String.format("%s already defined!", aName.getText()));
293
        }
294

    
295

    
296

    
297
        /* create a named type; we're on top-level here */
298
         void createNamedType(Token aName, Type aType)
299
        {
300
                // precond..
301
                assert(aName != null);
302

    
303
                if (aType == null)
304
                {
305
                        doError(aName, String.format("%s lacks a type! (Type not added)", aName.getText()));
306
                        return;
307
                }
308

    
309

    
310
                if (pState.currentScope.ResolveIdentifier(aName.getText()) == null)
311
                {
312
                        final TypeIdentifier newid = new TypeIdentifier(aName, aType, GetScope());
313
                        aType.SetTypeIdentifier(newid);
314
                        pState.currentScope.AddIdentifier(newid, null);
315
                }
316
                else
317
                        doError(aName, String.format("%s already defined!", aName.getText()));
318

    
319
        }
320

    
321
        /* create basic structure for an ooa-system descr. resolve stack TOS is now ooa-system symbols */
322
        OoActionSystemType createOoaType(Token refinesSystemName, boolean autoCons)
323
        {
324
                final Identifier refinedSystem = pState.Lookup(refinesSystemName);
325
                OoActionSystemType refinedSystemType = null;
326
                if ((refinedSystem != null) && (refinedSystem.type() != null))
327
                {
328
                        if (refinedSystem.type().kind() != TypeKind.OoActionSystemType)
329
                                doError(refinesSystemName,
330
                                                String.format("%s not an object oriented action system", refinesSystemName.getText()));
331
                        else
332
                                refinedSystemType = (OoActionSystemType)refinedSystem.type();
333
                }
334
                else if (refinesSystemName != null)
335
                {
336
                        pState.AddErrorMessage(
337
                                        new ParserError(pState.filename, refinesSystemName,
338
                                                        String.format("Type that's being refined (%s) not found!", refinesSystemName.getText())));
339
                }
340

    
341
                final OoActionSystemType result = new OoActionSystemType(autoCons, refinedSystemType, null);
342

    
343
                // add 'self' to the symbols.. (self is a keyword, so it can't be defined)
344
                result.AddIdentifier(new SelfTypeIdentifier("self", result, GetScope()), null);
345

    
346
                pState.PushResolveStack(result);
347
                return result;
348
        }
349

    
350
        /* remove ooa-system symbols from resolve stack TOS */
351
        void fixupOoaType(OoActionSystemType aTypeSymbol)
352
        {
353
                if (aTypeSymbol == null)
354
                        return;
355

    
356
                aTypeSymbol.SetupAnonymousName();
357
                if (aTypeSymbol != null)
358
                        pState.PopResolveStack();
359
        }
360

    
361
        Expression addCastExpression(Expression e, Token cid)
362
        {
363
                assert(e != null);
364

    
365
                final Expression result = new UnaryOperator(ExpressionKind.Cast, e, cid.getLine(), cid.getCharPositionInLine());
366
                result.SetType(new OpaqueType(new TypeIdentifier(cid, null, GetScope())));
367
                pState.typesToFixUp.add((OpaqueType)result.type());
368
                return result;
369
        }
370

    
371

    
372
        /* add a new ooa to the list describing the composition of action systems */
373
         void addToIdentifierList(IdentifierList top, Token aName)
374
        {
375
                assert(top != null);
376

    
377
                final Identifier aSym = pState.Lookup(aName);
378
                if (aSym == null)
379
                {
380
                        doError(aName, String.format("Could not find ooa-system %s!", aName.getText()));
381
                }
382
                else if ((aSym.type() == null) || !(aSym.type().kind() == TypeKind.OoActionSystemType))
383
                {
384
                        doError(aName, String.format("Referenced type (%s) does not have correct type!", aName.getText()));
385
                }
386
                else
387
                {
388
                        final OoActionSystemType aType = (OoActionSystemType)aSym.type();
389
                        if (aType.isInSystemDescription())
390
                                doError(aName, String.format("Referenced type (%s) already used in composition!", aName.getText()));
391
                        else
392
                                aType.SetIsInSystemDescription(true);
393
                        top.AddElement(aSym);
394
                }
395
        }
396

    
397
        /* does a fixup run after parsing */
398
         void fixUpRun(IdentifierList sysDescr)
399
        {
400
                // set system descr.
401
                pState.ooaSystem.SetSystemDescription(sysDescr);
402

    
403
                // fixup named types
404
                FixupNamedTypes();
405
        }
406

    
407
        private void FixupNamedTypes()
408
        {
409
                /*named type refs that could not be resolved in the first run, have to
410
          be resolved now. */
411
                for (final OpaqueType ntype: pState.typesToFixUp)
412
                {
413
                        if (ntype.resolvedType() == null)
414
                        {
415
                                //ntype.identifier
416
                                final Identifier asym = pState.Lookup(ntype.identifier().tokenText(), ntype.identifier().definingScope());
417
                                if ((asym == null) || (asym.kind() != IdentifierKind.TypeIdentifier))
418
                                {
419
                                        final ParserError error = new ParserError(pState.filename, ntype.identifier().line(), ntype.identifier().column(),
420
                                                        String.format("Can not resolve %s to a named type", ntype.identifier().tokenText()));
421
                                        pState.AddErrorMessage(error);
422
                                }
423
                                else
424
                                        ntype.SetResolvedType(asym.type());
425
                        }
426
                }
427
                pState.typesToFixUp.clear();
428
        }
429

    
430

    
431
        private boolean TosIsActionSystem()
432
        {
433
                return pState.currentScope instanceof OoActionSystemType;
434
        }
435

    
436

    
437
        private int currentLine()
438
        {
439
                final Token token = input.LT(-1);
440
                return token == null ? 0 : token.getLine();
441
        }
442

    
443
        private int currentPos()
444
        {
445
                final Token token = input.LT(-1);
446
                return token == null ? 0 : token.getCharPositionInLine();
447
        }
448

    
449
        /* add var symbol to the current action system */
450
        void createAttribute(Token varname, boolean isStatic, boolean isObs, boolean isCtr, Type aType, Expression anExpr)
451
        {
452
                if (!TosIsActionSystem())
453
                        return;
454

    
455
                if (aType == null)
456
                {
457
                        doError(varname, String.format("%s lacks type!", varname.getText()));
458
                }
459
                if (anExpr == null)
460
                {
461
                        doError(varname, String.format("%s lacks initializer!", varname.getText()));
462
                }
463
                if (isObs == true || isCtr == true)
464
                        doError(varname, "'obs' or 'ctr' on attributes not allowed");
465

    
466

    
467
                final AttributeIdentifier var = new AttributeIdentifier(varname, aType, GetScope(), anExpr, isStatic, isObs, isCtr);
468
                if (pState.currentScope.ResolveIdentifier(varname.getText()) == null)
469
                        pState.currentScope.AddIdentifier(var, null);
470
                else
471
                        doError(varname, String.format("Can not add %s: Symbol already defined!", varname.getText()));
472
        }
473

    
474

    
475
        /* create a boolean type */
476
        BoolType createBoolType()
477
        {
478
                return new BoolType(null);
479
        }
480

    
481
        /* create a char type */
482
        CharType createCharType()
483
        {
484
                return new CharType(null);
485
        }
486

    
487
        /* create an int type */
488
        @SuppressWarnings("unchecked")
489
        Type createIntType(Token rangeLow, Token rangeHigh)
490
        {
491
                int low = 0;
492
                int high = 0;
493

    
494
                if (rangeLow.getType() == ooaLexer.T_INFTY)
495
                        doError(rangeLow, "Infinity not supported.");
496
                if (rangeLow.getType() == ooaLexer.T_INFTY)
497
                        doError(rangeHigh, "Infinity not supported.");
498

    
499
                if (rangeLow.getType() == ooaLexer.T_IDENTIFIER)
500
                {
501
                        // see whether we can find the constant
502
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(rangeLow.getText());
503
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
504
                                doError(rangeLow, String.format("Constant %s not found", rangeLow.getText()));
505
                        else if (aconst.type().kind() != TypeKind.IntType)
506
                                doError(rangeLow, "Constant must be integer");
507
                        else
508
                                low = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
509
                }
510
                else
511
                        try {
512
                                low = Integer.parseInt(rangeLow.getText());
513
                        } catch (final NumberFormatException e) {
514
                                doError(rangeLow, "Can not convert to integer");
515
                        }
516

    
517
                if (rangeHigh.getType() == ooaLexer.T_IDENTIFIER)
518
                {
519
                        // see whether we can find the constant
520
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(rangeHigh.getText());
521
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
522
                                doError(rangeHigh, String.format("Constant %s not found", rangeHigh.getText()));
523
                        else if (aconst.type().kind() != TypeKind.IntType)
524
                                doError(rangeHigh, "Constant must be integer");
525
                        else
526
                                high = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
527
                }
528
                else
529
                        try {
530
                                high = Integer.parseInt(rangeHigh.getText());
531
                        } catch (final NumberFormatException e) {
532
                                doError(rangeLow, "Can not convert to integer");
533
                        }
534

    
535
                if (high < low)
536
                        doError(rangeHigh, "Lower bound greater than upper bound");
537

    
538
                return new IntType(low, high, null);
539
        }
540

    
541
        /* create a float type */
542
         @SuppressWarnings("unchecked")
543
        Type createFloatType(Token rangeLow, Token rangeHigh)
544
        {
545
                float low = 0;
546
                float high = 0;
547

    
548
                if (rangeLow.getType() == ooaLexer.T_INFTY)
549
                        doError(rangeLow, "Infinity not supported.");
550
                if (rangeLow.getType() == ooaLexer.T_INFTY)
551
                        doError(rangeHigh, "Infinity not supported.");
552

    
553
                if (rangeLow.getType() == ooaLexer.T_IDENTIFIER)
554
                {
555
                        // see whether we can find the constant
556
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(rangeLow.getText());
557
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
558
                                doError(rangeLow, String.format("Constant %s not found", rangeLow.getText()));
559
                        else if (aconst.type().kind() != TypeKind.FloatType)
560
                                doError(rangeLow, "Constant must be float");
561
                        else
562
                                low = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
563
                }
564
                else
565
                        try {
566
                                low = Float.parseFloat(rangeLow.getText());
567
                        } catch (final NumberFormatException e) {
568
                                doError(rangeLow, "Can not convert to float (single)");
569
                        }
570

    
571
                if (rangeHigh.getType() == ooaLexer.T_IDENTIFIER)
572
                {
573
                        // see whether we can find the constant
574
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(rangeHigh.getText());
575
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
576
                                doError(rangeHigh, String.format("Constant %s not found", rangeHigh.getText()));
577
                        else if (aconst.type().kind() != TypeKind.FloatType)
578
                                doError(rangeHigh, "Constant must be integer");
579
                        else
580
                                high = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
581
                }
582
                else
583
                        try {
584
                                high = Float.parseFloat(rangeHigh.getText());
585
                        } catch (final NumberFormatException e){
586
                                doError(rangeHigh, "Can not convert to float (single)");
587
                        }
588

    
589
                if (high < low)
590
                        doError(rangeHigh, "Lower bound greater than upper bound");
591

    
592
                /* precision */
593
                final float afterc_low = low -  (float)Math.floor(low); //(float)Convert.ToInt32(low);
594
                final float afterc_high = high - (float)Math.floor(high); //(float)Convert.ToInt32(high);
595
                final float precision = afterc_low < afterc_high ? afterc_low : afterc_high;
596

    
597
                return new FloatType(low, high, precision, null);
598
        }
599

    
600
        /* create a list of an enumerated type */
601
         Type createListEnumType(Token alistelem)
602
        {
603
                final EnumType hiddenEnumType = new EnumType(null);
604

    
605
                final ListType result = new ListType(hiddenEnumType, 500, null);
606
                addToListEnumType(result, alistelem);
607
                return result;
608
        }
609

    
610
        /* add a new enum symbol to a list with an anonymous enumerated type */
611
         void addToListEnumType(Type aTypeSymbol, Token otherlistelem)
612
        {
613
                final EnumType enumtype = (EnumType)((ListType)aTypeSymbol).innerType();
614
                addToEnumType(enumtype, otherlistelem, null);
615
        }
616

    
617
        /* create a new enumerated type */
618
         Type createEnumType(Token aRangeValue, Token anIntegerValue)
619
        {
620
                EnumType result;
621

    
622
                if (anIntegerValue == null)
623
                        result = new EnumType(null);
624
                else
625
                        result = new ValuedEnumType(null);
626

    
627
                addToEnumType(result, aRangeValue, anIntegerValue);
628
                return result;
629
        }
630

    
631
        /* add a new enum symbol to the enumerated type */
632
         void addToEnumType(Type aTypeSymbol, Token otherRangeValue, Token anIntegerValue)
633
        {
634
                final EnumType anEnum = (EnumType)aTypeSymbol;
635
                if (anEnum.symbolTable().Defined(otherRangeValue.getText()))
636
                {
637
                        doError(otherRangeValue, String.format("Element '%s' already defined!", otherRangeValue.getText()));
638
                        return;
639
                }
640

    
641
                /* for now we allow the usage of enum-ids without specifying the actual enum type,
642
                 * e.g., x = some_enum_id, hence all enum identifier must be globally unique.
643
                 * This decision could be reverted at later time...
644
                 */
645
                final Identifier sym = pState.Lookup(otherRangeValue);
646
                if (sym != null)
647
                {
648
                        doError(otherRangeValue, String.format("Element '%s' already defined!", otherRangeValue.getText()));
649
                        return;
650
                }
651

    
652
                EnumIdentifier enumval;
653
                if (anIntegerValue == null)
654
                {
655
                        if (aTypeSymbol instanceof ValuedEnumType)
656
                        {
657
                                doError(otherRangeValue, String.format("Element '%s' needs integer value!", otherRangeValue.getText()));
658
                                return;
659
                        }
660

    
661
                        enumval = new EnumIdentifier(otherRangeValue, (EnumType)aTypeSymbol, GetScope());
662
                }
663
                else
664
                {
665
                        if (!(aTypeSymbol instanceof ValuedEnumType))
666
                        {
667
                                doError(otherRangeValue, String.format("Element '%s' must not have integer value!", otherRangeValue.getText()));
668
                                return;
669
                        }
670
                        enumval = new EnumIdentifier(otherRangeValue, Integer.parseInt(anIntegerValue.getText()), (EnumType)aTypeSymbol, GetScope());
671
                }
672

    
673
                ((EnumType)aTypeSymbol).AddEnumSymbol(enumval);
674

    
675
                /* add the enum id to 'global' state */
676
                pState.currentScope.AddIdentifier(enumval, null);
677
        }
678

    
679
        /* get a named type */
680
         Type getNamedType(Token aType)
681
        {
682
                Type result = null;
683
                final Identifier sym = pState.Lookup(aType);
684
                if (sym == null)
685
                {
686
                        /* we might not have seen this type yet - so do a fixup run later */
687
                        result = new OpaqueType(new TypeIdentifier(aType, null, GetScope()));
688
                        pState.typesToFixUp.add((OpaqueType)result);
689
                }
690
                else if (sym.kind() == IdentifierKind.TypeIdentifier)
691
                        result = ((TypeIdentifier)sym).type();
692
                else
693
                        doError(aType, "Not a named type symbol: " + aType.getText());
694

    
695
                return result;
696
        }
697

    
698
        /* create a list type */
699
         @SuppressWarnings("unchecked")
700
        Type createListType(Token numOfElements, Type innertype)
701
        {
702
                if (innertype == null)
703
                        doError(numOfElements, "List type lacks proper element type (null)");
704

    
705
                int numElems = 0;
706

    
707
                if (numOfElements.getType() == ooaLexer.T_IDENTIFIER)
708
                {
709
                        // see whether we can find the constant
710
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(numOfElements.getText());
711
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
712
                                doError(numOfElements, String.format("Constant %s not found", numOfElements.getText()));
713
                        else if (aconst.type().kind() != TypeKind.IntType)
714
                                doError(numOfElements, "Constant must be integer");
715
                        else
716
                                numElems = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
717
                }
718
                else
719
                {
720
                        try {
721
                                numElems = Integer.parseInt(numOfElements.getText());
722
                        } catch (final NumberFormatException e) {
723
                                doError(numOfElements, "Not an integer");
724
                        }
725
                        if (numElems <= 0)
726
                                doError(numOfElements, "Number of elements in a list must be >= 1");
727
                }
728

    
729
                final ListType result = new ListType(innertype, numElems, null);
730
                return result;
731
        }
732

    
733
        /* create a map type */
734
         @SuppressWarnings("unchecked")
735
        Type createMapType(Token numOfElements, Type mapfromtype, Type maptotype)
736
        {
737
                if (mapfromtype == null)
738
                        doError(numOfElements, "Map: From-type not set (null)");
739
                if (maptotype == null)
740
                        doError(numOfElements, "Map: To-type not set (null)");
741

    
742
                int max = 0;
743

    
744
                if (numOfElements.getType() == ooaLexer.T_IDENTIFIER)
745
                {
746
                        // see whether we can find the constant
747
                        final Identifier aconst = pState.currentScope.ResolveIdentifier(numOfElements.getText());
748
                        if (aconst == null || aconst.kind() != IdentifierKind.Constant)
749
                                doError(numOfElements, String.format("Constant %s not found", numOfElements.getText()));
750
                        else if (aconst.type().kind() != TypeKind.IntType)
751
                                doError(numOfElements, "Constant must be integer");
752
                        else
753
                                max = ((ValueExpression<Integer>)((ConstantIdentifier)aconst).Value()).value();
754
                }
755
                else
756
                        try {
757
                                max = Integer.parseInt(numOfElements.getText());
758
                        } catch (final NumberFormatException e) {
759
                                doError(numOfElements, "Not an integer");
760
                        }
761

    
762
                final MapType result = new MapType(mapfromtype, maptotype, max, null);
763
                return result;
764
        }
765

    
766
        /* create a tuple type */
767
         Type createTupleType(Type aType)
768
        {
769
                final TupleType result = new TupleType(null);
770
                addToTupleType(result, aType);
771
                return result;
772
        }
773

    
774
        /* add inner type to tuple */
775
         void addToTupleType(Type aTypeSymbol, Type anotherType)
776
        {
777
                final TupleType tuple = (TupleType)aTypeSymbol;
778
                if (anotherType != null)
779
                        tuple.AddType(anotherType);
780
                else
781
                        doError("Unknown inner type in tuple");
782
        }
783

    
784
        /* gets called after a simple type has been constructed. used to define an internal name*/
785
         void fixupSimpleType(Type aTypeSymbol)
786
        {
787
                if (aTypeSymbol != null)
788
                        aTypeSymbol.SetupAnonymousName();
789
        }
790

    
791
        /* gets called after a simple or complex type has been constructed. used to define an internal name */
792
         void fixupComplexType(Type aTypeSymbol)
793
        {
794
                if (aTypeSymbol != null)
795
                        aTypeSymbol.SetupAnonymousName();
796
        }
797

    
798

    
799
        /* create a method symbol */
800
         FunctionIdentifier createMethodSymbol(Token mname)
801
        {
802
                final Identifier sym = pState.Lookup(mname);
803
                if (sym != null)
804
                {
805
                        doError(mname, String.format("Redefinition of %s", mname.getText()));
806
                        return null;
807
                }
808

    
809
                final FunctionType funtype = new FunctionType(FunctionTypeEnum.Method, new LinkedList<Type>(), null);
810
                final MethodIdentifier msym = new MethodIdentifier(mname, funtype, GetScope());
811
                // funtype.SetTypeIdentifier(msym); -- the type of this function doesn't have a name!
812

    
813
                pState.currentScope.AddIdentifier(msym, null);
814

    
815
                pState.PushResolveStack(msym);
816
                return msym;
817
        }
818

    
819
        /* remove local method symbols from resolution stack again */
820
        protected void popResolveStack(FunctionIdentifier newMethod)
821
        {
822
                if (newMethod != null)
823
                        pState.PopResolveStack();
824
        }
825

    
826

    
827
        /* add a return type to a method */
828
         void setMethodReturnType(FunctionIdentifier newMethod, Type rt)
829
        {
830
                if (newMethod == null)
831
                        return;
832

    
833
                if (rt == null)
834
                        doError(String.format("Method %s has no return type (null)", newMethod.tokenText()));
835

    
836
                /* set return type */
837
                ((FunctionType)newMethod.type()).SetReturnType(rt);
838

    
839

    
840
                /* add hidden return parameter */
841
                if (newMethod.symbolTable().Defined("result"))
842
                {
843
                        doError(String.format("Method %s defines 'result'", newMethod.tokenText()));
844
                        return;
845
                }
846

    
847
                final ParameterIdentifier returnval = new ParameterIdentifier("result", rt, GetScope());
848
                newMethod.symbolTable().AddIdentifier(returnval);
849
        }
850

    
851
        /* add a parameter to a method */
852
         void addMethodParameter(FunctionIdentifier newMethod, Token paramName, Type atype)
853
        {
854
                if (newMethod == null)
855
                        return;
856

    
857
                if (atype == null)
858
                        doError(paramName, "Parameter has no type (null)");
859

    
860

    
861
                if (newMethod.symbolTable().Defined(paramName.getText()) == true)
862
                {
863
                        doError(paramName, String.format("Parameter '%s' already defined", paramName.getText()));
864
                        return;
865
                }
866

    
867
                // add parameter to scope
868
                final ParameterIdentifier param = new ParameterIdentifier(paramName, atype, GetScope());
869
                newMethod.AddParameter(param);
870

    
871
                // add type of param to signature
872
                final FunctionType ftype = (FunctionType)newMethod.type();
873
                ftype.AddParameterType(atype);
874
        }
875

    
876
        /* set method body of a method */
877
         void addMethodBody(FunctionIdentifier newMethod, Block statements)
878
        {
879
                if (newMethod == null)
880
                        return;
881

    
882
                if (statements == null)
883
                        doError(String.format("%s has empty body (null)",
884
                                        ((FunctionType)newMethod.type()).functionType() == FunctionTypeEnum.Method ? "Method" : "Action"));
885

    
886
                newMethod.SetBody(statements);
887
        }
888

    
889
        /* create a continuous action */
890
         FunctionIdentifier createNamedContinuousAction(Token cactionname, FunctionTypeEnum actionTypeEnum)
891
        {
892
                return createNamedAction(cactionname, actionTypeEnum);
893
        }
894

    
895
        /* create a named action */
896
         FunctionIdentifier createNamedAction(Token actionname, FunctionTypeEnum actionType)
897
        {
898
                final Identifier sym = pState.Lookup(actionname);
899
                if (sym != null)
900
                {
901
                        doError(actionname, String.format("Symbol '%s' already defined.", sym.tokenText()));
902
                        return null;
903
                }
904

    
905
                final FunctionType atype = new FunctionType(actionType, new LinkedList<Type>(), null);
906
                final NamedActionIdentifier action = new NamedActionIdentifier(actionname, atype, GetScope());
907
                // atype.SetTypeIdentifier(action); -- the type of this action doesn't have a name!
908

    
909
                pState.currentScope.AddIdentifier(action, null);
910
                pState.PushResolveStack(action);
911
                return action;
912
        }
913

    
914
        /* add body of action */
915
         void addActionBody(FunctionIdentifier newAction, GuardedCommand body)
916
        {
917
                // we need a wrapper around the guarded command..
918
                final Block bdy = new SeqBlock(currentLine(), currentPos());
919
                addMethodBody(newAction, bdy);
920
                body.SetParentScope(bdy);
921
                bdy.AddStatement(body);
922
        }
923

    
924
        /* add constraints of cont. action */
925
         void addContinuousActionBody(FunctionIdentifier newAction, GuardedCommand constraints)
926
        {
927
                final Block bdy = new SeqBlock(currentLine(), currentPos());
928
                bdy.AddStatement(constraints);
929
                addMethodBody(newAction, bdy);
930
        }
931

    
932
        /* create a guarded command */
933
         GuardedCommand createGuardedCommandStatement()
934
         {
935
                 return new GuardedCommand(null, null, currentLine(), currentPos());
936
         }
937

    
938
         void addExprAndBlockToGuardedCommand(GuardedCommand cmd, Expression expr, Block bdy)
939
        {
940
                if (bdy == null)
941
                        doError("Guarded command without body (null)!");
942

    
943
                if (expr == null)
944
                        doError("Guarded command without guard (null)!");
945

    
946
                cmd.SetGuard(expr);
947
                cmd.SetBody(bdy);
948
        }
949
         GuardedCommand createGuardedCommandStatement(Expression expr, Block bdy, boolean isQualitative)
950
        {
951
                final GuardedCommand result = createGuardedCommandStatement();
952
                addExprAndBlockToGuardedCommand(result, expr, bdy);
953
                result.SetIsQualitative(isQualitative);
954
                return result;
955
        }
956

    
957
        /* add statements to list */
958
         void addToStatementList(Block top, Statement stmt)
959
        {
960
                if (stmt == null)
961
                        doError("Can not add statement: null!");
962

    
963
                top.AddStatement(stmt);
964
        }
965

    
966
        /* create a Kill statement */
967
         Statement createKillStatement(Token aname)
968
        {
969
                final Identifier sym = pState.Lookup(aname);
970
                if (sym == null)
971
                        doError(aname, "Not defined");
972

    
973
                final KillStatement result = new KillStatement(sym, aname.getLine(), aname.getCharPositionInLine());
974
                return result;
975
        }
976

    
977
        /* create a Skip statement */
978
         Statement createSkipStatement()
979
        {
980
                return new SkipStatement(currentLine(), currentPos());
981
        }
982

    
983
        /* create a Break statement */
984
         Statement createBreakStatement()
985
        {
986
                return new BreakStatement(currentLine(), currentPos());
987
        }
988

    
989
        /* create an Abort statement */
990
         Statement createAbortStatement()
991
        {
992
                return new AbortStatement(currentLine(), currentPos());
993
        }
994

    
995
        /* creates a prioritized composition block */
996
         Block createPrioBlock(Block top)
997
        {
998
                return new PrioBlock(top, currentLine(), currentPos());
999
        }
1000

    
1001
        /* creates a nondeterministically composed block */
1002
         Block createNondetBlock(Block top)
1003
        {
1004
                return new NondetBlock(top, currentLine(), currentPos());
1005
        }
1006

    
1007
        /* creates a sequentially composed block */
1008
         SeqBlock createSeqBlock(Block top)
1009
        {
1010
                return new SeqBlock(top, currentLine(), currentPos());
1011
        }
1012

    
1013

    
1014
        /* adds a filter expression to seq block */
1015
        protected void addSeqBlockExpression(Block seqList, Expression sexpr)
1016
        {
1017
                seqList.SetFilter(sexpr); /*gets transformed to guarded command in resolvevisitor!*/
1018
        }
1019

    
1020

    
1021
        /* create a self identifier */
1022
         IdentifierExpression createSelfIdentifierExpression(Token self)
1023
        {
1024
                final Identifier id = pState.Lookup("self");
1025
                if (id == null)
1026
                {
1027
                        doError(self, "Can not resolve 'self'");
1028
                        return null;
1029
                }
1030

    
1031
                final IdentifierExpression result = new IdentifierExpression(id, self.getLine(), self.getCharPositionInLine());
1032
                result.setIsSelf(true);
1033
                return result;
1034
        }
1035

    
1036
        /* build up identifier tree... */
1037
         Expression createIdentifierAccessExpression(IdentifierExpression aself, Token token)
1038
        {
1039
                final Identifier someid = pState.Lookup(token.getText(), GetScope());
1040
                final Identifier self = pState.Lookup("self");
1041

    
1042
                if (someid != null)
1043
                {
1044
                        switch (someid.kind())
1045
                        {
1046
                        /* all method and attribute accesses are prefixed by self */
1047
                        case AttributeIdentifier:
1048
                        case MethodIdentifier:
1049
                                if (self == null)
1050
                                        doError(token, "Self access of method: Can not find 'self' symbol! (internal error)");
1051
                                aself = new IdentifierExpression(self, token.getLine(), token.getCharPositionInLine());
1052
                                aself.setIsSelf(true);
1053
                                break;
1054
                        default:
1055
                                break;
1056
                        }
1057
                }
1058

    
1059
                final IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
1060
                if (aself != null)
1061
                        return new AccessExpression(aself, ident, token.getLine(), token.getCharPositionInLine());
1062
                else
1063
                        return ident;
1064
        }
1065

    
1066
         AccessExpression addIdentifierAccessExpression(Expression parent, Token token)
1067
        {
1068
                final IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
1069
                return new AccessExpression(parent, ident, token.getLine(), token.getCharPositionInLine());
1070
        }
1071

    
1072
        /* we have a primed id; prime the complete subtree.. */
1073
        Expression setIdentifierExpressionPrimed(Expression oldExpr, Token token)
1074
        {
1075
                return new UnaryOperator(ExpressionKind.Primed, oldExpr, token.getLine(), token.getCharPositionInLine());
1076
        }
1077

    
1078
        /* create a fold operation */
1079
         Expression createFoldExpression(Expression result, Token afold, Expression initval, Expression anexpr)
1080
        {
1081
                ExpressionKind akind = ExpressionKind.foldLR;
1082
                if (afold.getType() == ooaLexer.T_FOLDLR)
1083
                        akind = ExpressionKind.foldLR;
1084
                else if (afold.getType() == ooaLexer.T_FOLDRL)
1085
                        akind = ExpressionKind.foldRL;
1086
                else
1087
                        assert(false);
1088

    
1089
                final TernaryOperator op = new TernaryOperator(akind, result, initval, anexpr, currentLine(), currentPos(), GetScope());
1090
                return op;
1091
        }
1092

    
1093

    
1094
        /* create a method access */
1095
         CallExpression createMethodAccessExpression(Expression subexpr, List<Expression> m_params, Token token)
1096
        {
1097
                assert(subexpr != null);
1098

    
1099
                return new CallExpression(subexpr, m_params, token.getLine(), token.getCharPositionInLine(), GetScope());
1100
        }
1101

    
1102
        /* create a tuple or map access */
1103
         TupleMapAccessExpression createTupleMapAccessExpression(Expression subexpr, Expression ac, Token token)
1104
        {
1105
                assert(subexpr != null);
1106

    
1107
                return new TupleMapAccessExpression(subexpr, ac, token.getLine(), token.getCharPositionInLine());
1108
        }
1109

    
1110
        /* create a method call statement; has to be resolved in a second run */
1111
         Statement createCallStatement(Expression aqname)
1112
        {
1113
                return new Call(aqname, currentLine(), currentPos());
1114
        }
1115

    
1116
        /* create a single assignment statement */
1117
         Statement createSingleAssignmentStatement(Expression aqname, Expression aexp)
1118
        {
1119
                final Assignment result = new Assignment(aqname, aexp, null, currentLine(), currentPos());
1120
                return result;
1121
        }
1122

    
1123
        /* create a multi-assignment statement; has to be resolved in a second run */
1124
         Statement createMultipleAssignmentStatementLHS(Expression aqname)
1125
        {
1126
                return new Assignment(aqname, null, null, currentLine(), currentPos());
1127
        }
1128

    
1129
        /* adds an expression to the multi-assign */
1130
         void addMutlipleAssignmentStatementRHS(Statement result, Expression mexp)
1131
        {
1132
                ((Assignment)result).AddValue(mexp);
1133
        }
1134

    
1135
        /* adds a LHS-var to the multi assign */
1136
         void addMultipleAssignmentStatementLHS(Statement result, Expression malhs)
1137
        {
1138
                ((Assignment)result).AddPlace(malhs);
1139
        }
1140

    
1141
        /* pop an assignment statement from the resolve stack */
1142
         void popAssignmentOffResolveStack(Statement result)
1143
        {
1144
                assert(result == pState.currentScope); // ref eq.
1145
                pState.PopResolveStack();
1146
        }
1147

    
1148
        /* pushes the assignment statement onto resolve stack. */
1149
         void pushAssignmentOnResolveStack(Statement result)
1150
        {
1151
                assert(result instanceof Assignment);
1152
                pState.PushResolveStack((Assignment)result);
1153
        }
1154

    
1155

    
1156
        /* adds a nondet-assignment constraint */
1157
         void addConstraintToAssignment(Statement result, Expression ndexp)
1158
        {
1159
                ((Assignment)result).SetNondetExpression(ndexp);
1160
        }
1161

    
1162
        /* add a named action call to do-od block */
1163
         void addNamedActionCallToBlockList(Block top, Token aname, List<Expression> m_params, Token maptoken, Expression amapexpression)
1164
        {
1165
                final Identifier id = pState.Lookup(aname);
1166
                if (id == null)
1167
                {
1168
                        doError(aname, String.format("Could not find named action '%s'", aname.getText()));
1169
                        return;
1170
                }
1171
                Expression callexpr;
1172
                if (id.kind() == IdentifierKind.MethodIdentifier)
1173
                {
1174
                        doError(aname, "Method access in do-od block not allowed.");
1175
                        return;
1176
                        // access via self
1177
                        /*
1178
            Identifier self = pState.Lookup("self");
1179
            if (self == null)
1180
                doError(aname, "Self access of method: Can not find 'self' symbol! (internal error)");
1181
            IdentifierExpression aself = new IdentifierExpression(self, aname.getLine(), aname.getCharPositionInLine());
1182
            aself.setIsSelf(true);
1183
            callexpr = new CallExpression(
1184
                new AccessExpression(aself,
1185
                    new IdentifierExpression(id, aname.getLine(), aname.getCharPositionInLine()), aname.getLine(), aname.getCharPositionInLine()),
1186
                    m_params, aname.getLine(), aname.getCharPositionInLine(), GetScope());
1187
                         */
1188
                }
1189
                else
1190
                        callexpr = new CallExpression(
1191
                                        new IdentifierExpression(id, aname.getLine(), aname.getCharPositionInLine()),
1192
                                        m_params, aname.getLine(), aname.getCharPositionInLine(), GetScope());
1193

    
1194
                if (amapexpression != null)
1195
                {
1196
                        ExpressionKind akind = ExpressionKind.foldLR;
1197
                        if (maptoken.getType() == ooaLexer.T_FOLDLR)
1198
                                akind = ExpressionKind.foldLR;
1199
                        else if (maptoken.getType() == ooaLexer.T_FOLDRL)
1200
                                akind = ExpressionKind.foldRL;
1201
                        else
1202
                                assert(false);
1203

    
1204
                        callexpr = new TernaryOperator(akind, callexpr, null, amapexpression,
1205
                                        currentLine(), currentPos(), GetScope());
1206
                }
1207
                final Call statement = new Call(callexpr, currentLine(), currentPos());
1208
                top.AddStatement(statement);
1209
        }
1210

    
1211
        /*adds skip statement instead of call to do-od block*/
1212
         void addSkipStatementToBlockList(Block top)
1213
        {
1214
                top.AddStatement(new SkipStatement(currentLine(), currentPos()));
1215
        }
1216

    
1217

    
1218
        /* add anonymous action to do-od block */
1219
         void addToBlockList(Block top, Statement gcmd)
1220
        {
1221
                if (gcmd != null)
1222
                        top.AddStatement(gcmd);
1223
        }
1224

    
1225
        /* add the do-od block to the action system type */
1226
         void addActionBlock(OoActionSystemType aTypeSymbol, Block bl)
1227
        {
1228
                aTypeSymbol.SetDoOdBlock(bl);
1229
        }
1230

    
1231
        /* push block */
1232
         void pushBlockToResolveStack(IScope toPush)
1233
        {
1234
                pState.PushResolveStack(toPush);
1235
        }
1236

    
1237
        /* pop block */
1238
         void popBlockFromResolveStack(IScope toPop)
1239
        {
1240
                if (toPop != null)
1241
                {
1242
                        assert(pState.currentScope == toPop); // ref eq.
1243
                        pState.PopResolveStack();
1244
                }
1245
        }
1246

    
1247
        /* add block var */
1248
         void addBlockVariable(Block seqList, Token varname, Type aType)
1249
        {
1250
                if (aType == null)
1251
                {
1252
                        doError(varname, String.format("%s lacks type!", varname.getText()));
1253
                }
1254
                try
1255
                {
1256
                        seqList.AddIdentifier(new LocalVariableIdentifier(varname, aType, GetScope()));
1257
                }
1258
                catch (final ArgumentException e)
1259
                {
1260
                        doError(varname, String.format("%s redefined!", varname.getText()));
1261
                }
1262
        }
1263

    
1264
        /* creates a general binary operator without any children */
1265
         BinaryOperator createBinaryOperator(ExpressionKind akind)
1266
        {
1267
                final Token token = input.LT(-1);
1268
                return new BinaryOperator(akind, null, null, token.getLine(), token.getCharPositionInLine());
1269
        }
1270

    
1271

    
1272
        /* creates a general unary operator without child */
1273
         UnaryOperator createUnaryOperator(ExpressionKind unaryOperatorType)
1274
        {
1275
                final Token token = input.LT(-1);
1276
                return new UnaryOperator(unaryOperatorType, null, token.getLine(), token.getCharPositionInLine());
1277
        }
1278

    
1279
        /* create a conditional expression */
1280
         Expression createConditionalExpression(Expression ce, Expression te, Expression ee, Token ef)
1281
        {
1282
                return new TernaryOperator(ExpressionKind.conditional, ce, te, ee, ef.getLine(), ef.getCharPositionInLine(), GetScope());
1283
        }
1284

    
1285
        /* create a quantifier expression */
1286
         Quantifier createQuantifierExpression(Token t)
1287
        {
1288
                Quantifier result = null;
1289
                if (t.getType() == ooaLexer.T_FORALL)
1290
                        result = new ForallQuantifier(null, t.getLine(), t.getCharPositionInLine());
1291
                else
1292
                        result = new ExistsQuantifier(null, t.getLine(), t.getCharPositionInLine());
1293

    
1294

    
1295
                pState.PushResolveStack(result);
1296
                return result;
1297
        }
1298

    
1299
        /* add a bound variable to the quantifier */
1300
         void addBoundVarToQuantifierExpression(Quantifier result, Token id, Type id_type)
1301
        {
1302
                /*note: this might be a bit harsh, but for now it's easier to demand uniquely named vars,
1303
                without any hiding. Could be fixed in searching only the first resolve level for
1304
                dupes..
1305
                 */
1306
                final Identifier sym = pState.Lookup(id);
1307
                if (sym != null)
1308
                        doError(id, String.format("'%s' already defined!", id.getText()));
1309
                else
1310
                {
1311
                        if (id_type == null)
1312
                                doError(id, String.format("%s lacks type (null).", id.getText()));
1313
                        final Identifier newvar = new ExpressionVariableIdentifier(id, id_type, GetScope());
1314
                        result.AddIdentifier(newvar, null);
1315
                }
1316
        }
1317

    
1318
        /* add the expression to the quantifier */
1319
         void addExpressionToQuantifier(Quantifier result, Expression e)
1320
        {
1321
                result.SetChild(e);
1322
        }
1323

    
1324
        /* remove local variables from resolve stack */
1325
         void removeBoundVarsFromResolveStack(Quantifier result)
1326
        {
1327
                if (result != null)
1328
                        pState.PopResolveStack();
1329
        }
1330

    
1331

    
1332
        /* create a boolean constant */
1333
         LeafExpression createBoolConstant(boolean p)
1334
        {
1335
                final Token token = input.LT(-1);
1336
                return new ValueExpression<Boolean>(p, token.getLine(), token.getCharPositionInLine(), Boolean.class);
1337
        }
1338

    
1339
        /* create a nil */
1340
         LeafExpression createNullPointerConstant()
1341
        {
1342
                final Token token = input.LT(-1);
1343
                return new ValueExpression<Object>(null, token.getLine(), token.getCharPositionInLine(), Object.class);
1344
        }
1345

    
1346
        /* create a 'self' identifier */
1347
         LeafExpression createSelfPointer()
1348
        {
1349
                final Token token = input.LT(-1);
1350
                final Identifier self = pState.Lookup("self");
1351
                if (self == null)
1352
                {
1353
                        doError(token, "Could not resolve 'self'");
1354
                        return new UnresolvedIdentifierExpression(token, GetScope());
1355
                }
1356

    
1357
                final IdentifierExpression result = new IdentifierExpression(self, token.getLine(), token.getCharPositionInLine());
1358
                result.setIsSelf(true);
1359

    
1360
                return result;
1361
        }
1362

    
1363
        /* create a float const */
1364
         LeafExpression createFloatConstant(Token t_fl)
1365
        {
1366
                return new ValueExpression<Double>(Double.parseDouble(t_fl.getText()), t_fl.getLine(), t_fl.getCharPositionInLine(), Double.class);
1367
        }
1368

    
1369
        /* create int const */
1370
         LeafExpression createIntConstant(Token t_in)
1371
        {
1372
                return new ValueExpression<Integer>(Integer.parseInt(t_in.getText()), t_in.getLine(), t_in.getCharPositionInLine(), Integer.class);
1373
        }
1374

    
1375
        /* set children of binary operator*/
1376
         Expression addBinaryExpression(BinaryOperator binexpr, Expression expr, Expression e2)
1377
        {
1378
                binexpr.SetLeftChild(expr);
1379
                binexpr.SetRightChild(e2);
1380
                return binexpr;
1381
        }
1382

    
1383
        /* set child of unary expr */
1384
         Expression addUnaryExpression(UnaryOperator unexpr, Expression e)
1385
        {
1386
                if (unexpr != null)
1387
                {
1388
                        unexpr.SetChild(e);
1389
                        return unexpr;
1390
                }
1391
                else
1392
                        return e;
1393
        }
1394

    
1395

    
1396

    
1397
        /* create a list */
1398
         ListConstructor createInitializedList()
1399
        {
1400
                final Token nexttoken = input.LT(1);
1401
                return new ListConstructor(nexttoken.getLine(), nexttoken.getCharPositionInLine());
1402
        }
1403

    
1404
        /* add an element to the list */
1405
         void addListElement(ListConstructor result, Expression e)
1406
        {
1407
                result.AddElement(e);
1408
        }
1409

    
1410
        /* push list comprehension vars on resolve stack */
1411
         void pushListVarsOnResolveStack(ListConstructor result)
1412
        {
1413
                pState.PushResolveStack(result);
1414
        }
1415

    
1416
        /* pop list comprehension vars from resolve stack */
1417
         void popListVarsFromResolveStack(ListConstructor result)
1418
        {
1419
                if (result != null)
1420
                        pState.PopResolveStack();
1421
        }
1422

    
1423
        /* set list comprehension expression */
1424
         void addListComprExpr(ListConstructor result, Expression e)
1425
        {
1426
                result.SetComprehension(e);
1427
        }
1428

    
1429
        /* add list comprehension variable */
1430
         void addListComprVar(ListConstructor result, Token id, Type t1)
1431
        {
1432
                final Identifier sym = pState.Lookup(id);
1433
                if (sym != null)
1434
                {
1435
                        /* see notes in quantifier*/
1436
                        doError(id, String.format("'%s' already defined.", id.getText()));
1437
                }
1438
                else
1439
                {
1440
                        final ExpressionVariableIdentifier newvar = new ExpressionVariableIdentifier(id, t1, GetScope());
1441
                        result.AddIdentifier(newvar, null);
1442
                }
1443
        }
1444

    
1445
        /* converts a String into a list of char */
1446
         ListConstructor createStringConstant(Token t_l)
1447
        {
1448
                final ListConstructor result = new ListConstructor(t_l.getLine(), t_l.getCharPositionInLine());
1449
                final String substr = t_l.getText().substring(1, t_l.getText().length() - 2);
1450
                for (int cntr = 0; cntr < substr.length(); cntr++) {
1451
                        final char c = substr.charAt(cntr);
1452
                        result.AddElement(new ValueExpression<Character>(c, t_l.getLine(), t_l.getCharPositionInLine(), Character.class));
1453
                }
1454
                return result;
1455
        }
1456

    
1457
        /* creates an empty map */
1458
         Expression createEmptyMap()
1459
        {
1460
                final Token token = input.LT(-1);
1461
                return new MapConstructor(token.getLine(), token.getCharPositionInLine());
1462
        }
1463

    
1464
        /* create a map and populate it with two items.. */
1465
         Expression createMap(Expression e1, Expression e2, Token am)
1466
        {
1467
                final MapConstructor result = new MapConstructor(am.getLine(), am.getCharPositionInLine());
1468
                result.AddItem(e1, e2);
1469
                return result;
1470
        }
1471

    
1472
        /* add a key/value pair to a map */
1473
         void addToMap(Expression map, Expression e3, Expression e4)
1474
        {
1475
                ((MapConstructor)map).AddItem(e3, e4);
1476
        }
1477

    
1478
        /* create a set */
1479
         SetConstructor createSet()
1480
        {
1481
                final Token nexttoken = input.LT(1);
1482
                final SetConstructor result = new SetConstructor(nexttoken.getLine(), nexttoken.getCharPositionInLine());
1483
                return result;
1484
        }
1485

    
1486
        /* add item to set */
1487
         void addToSet(Expression result, Expression e2)
1488
        {
1489
                ((SetConstructor)result).AddItem(e2);
1490
        }
1491

    
1492
        /* remove set comprehension variables from resolution stack */
1493
         void popSetVarsFromResolveStack(SetConstructor _set)
1494
        {
1495
                if (_set != null)
1496
                        pState.PopResolveStack();
1497
        }
1498

    
1499
        /* add set comprehension variables to resolution stack */
1500
         void pushSetVarsOnResolveStack(SetConstructor _set)
1501
        {
1502
                pState.PushResolveStack(_set);
1503
        }
1504

    
1505
        /* set comprehension expression fro set */
1506
         void addSetComprExpr(SetConstructor _set, Expression epx)
1507
        {
1508
                _set.SetComprehension(epx);
1509
        }
1510

    
1511
        /* add local set compr. variable */
1512
         void addSetComprVar(SetConstructor _set, Token id1, Type t1)
1513
        {
1514
                final Identifier sym = pState.Lookup(id1);
1515
                if (sym != null)
1516
                        doError(id1, String.format("'%s' already defined!", id1.getText()));
1517
                else
1518
                {
1519
                        final ExpressionVariableIdentifier newvar = new ExpressionVariableIdentifier(id1, t1, GetScope());
1520
                        _set.AddIdentifier(newvar, null);
1521
                }
1522
        }
1523

    
1524
        /* check whether identifier p is a tuple type */
1525
         boolean isTuple(String p)
1526
        {
1527
                final Identifier sym = pState.Lookup(p);
1528
                return (sym != null)
1529
                                && (sym.kind() == IdentifierKind.TypeIdentifier)
1530
                                && (sym.type().kind() == TypeKind.TupleType);
1531
        }
1532

    
1533
        /* create an initialized tuple */
1534
         Expression createInitializedTuple(Token aName, List<Expression> m_params)
1535
        {
1536
                final Identifier sym = pState.Lookup(aName);
1537
                if ((sym == null) || !(sym.type() instanceof TupleType))
1538
                {
1539
                        doError(aName, "Not a tuple type!");
1540
                        return null;
1541
                }
1542

    
1543
                final TupleType atuple = (TupleType)sym.type();
1544
                if (atuple.innerTypes().size() != m_params.size())
1545
                {
1546
                        doError(aName, "Number of parameters does not match type definition!");
1547
                        return null;
1548
                }
1549

    
1550
                return new TupleConstructor(sym, m_params, aName.getLine(), aName.getCharPositionInLine());
1551
        }
1552

    
1553

    
1554
        /* create an reference expression: (<expression>).xyz */
1555
         Expression createExpressionReference(Expression e, Expression aref, Token atoken)
1556
        {
1557
                final AccessExpression result = new AccessExpression(e, aref, atoken.getLine(), atoken.getCharPositionInLine());
1558
                return result;
1559
        }
1560

    
1561

    
1562
        /* gets called when we are parsing attributes */
1563
         void BeginParsingAttributes()
1564
        {
1565
                pState.parsingAttributes = true;
1566
        }
1567

    
1568
        /* gets called when we stop parsing attributes */
1569
         void EndParsingAttributes()
1570
        {
1571
                pState.parsingAttributes = false;
1572
        }
1573

    
1574
        /*dummy*/
1575
         boolean notIsAttributeInitialization()
1576
        {
1577
                return !pState.parsingAttributes;
1578
        }
1579

    
1580
        /* create a new(anid) constructor */
1581
        protected Expression createObject(Token anid)
1582
        {
1583
                if (!pState.parsingAttributes)
1584
                {
1585
                        doError(anid, "Object creation with 'new' only allowed in variable initializers.");
1586
                        return null;
1587
                }
1588

    
1589

    
1590
                final OpaqueType atype = new OpaqueType(new TypeIdentifier(anid, null, GetScope()));
1591
                pState.typesToFixUp.add(atype);
1592
                return new ObjectConstructor(atype, anid.getLine(), anid.getCharPositionInLine());
1593
        }
1594

    
1595

    
1596
        protected Expression createNamedObject(Token anid, Token aname)
1597
        {
1598
                if (!pState.parsingAttributes)
1599
                {
1600
                        doError(anid, "Object creation with 'new' only allowed in variable initializers.");
1601
                        return null;
1602
                }
1603

    
1604
                if (! aname.getText().matches("\"[_]*[a-zA-Z][a-zA-Z0-9_]*\""))
1605
                {
1606
                        doError(aname, "Not a valid identifier");
1607
                        return null;
1608
                }
1609

    
1610
                final OpaqueType atype = new OpaqueType(new TypeIdentifier(anid, null, GetScope()));
1611
                pState.typesToFixUp.add(atype);
1612
                return new ObjectConstructor(atype, aname.getText(), anid.getLine(), anid.getCharPositionInLine());
1613
        }
1614

    
1615
        /* add a local variable to a named action */
1616
         void addLocalVariableToNamedAction(FunctionIdentifier newMethod, Token id1, Type t1)
1617
        {
1618
                if (t1 == null)
1619
                {
1620
                        doError(id1, "Variable lacks type");
1621
                        return;
1622
                }
1623

    
1624
                final LocalVariableIdentifier lvar = new LocalVariableIdentifier(id1, t1, GetScope());
1625
                newMethod.AddIdentifier(lvar, null);
1626
        }
1627

    
1628
        /* ====== */
1629
        /* ====== */
1630

    
1631
        public static final LinkedHashMap<String, String> readableTokens = new LinkedHashMap<String, String>();
1632

    
1633

    
1634
//        private void SetUpTokenDictionary()
1635
        static
1636
        {
1637
//                if (readableTokens.size() > 0)
1638
//                        return;
1639
                readableTokens.put("<invalid>", "<invalid>");
1640
                readableTokens.put("<EOR>", "<EOR>");
1641
                readableTokens.put("<DOWN>", "<DOWN>");
1642
                readableTokens.put("<UP>", "<UP>");
1643
                readableTokens.put("T_TYPES", "'types'");
1644
                readableTokens.put("T_SYSTEM", "'system'");
1645
                readableTokens.put("T_SEMICOLON", "';'");
1646
                readableTokens.put("T_IDENTIFIER", "<identifier>");
1647
                readableTokens.put("T_EQUAL", "'='");
1648
                readableTokens.put("T_PRIO", "'//'");
1649
                readableTokens.put("T_NONDET", "'[]'");
1650
                readableTokens.put("T_LPAREN", "'('");
1651
                readableTokens.put("T_RPAREN", "')'");
1652
                readableTokens.put("T_LIST", "'list'");
1653
                readableTokens.put("T_LSQPAREN", "'['");
1654
                readableTokens.put("T_INTNUMBER", "<integer>");
1655
                readableTokens.put("T_RSQPAREN", "']'");
1656
                readableTokens.put("T_OF", "'of'");
1657
                readableTokens.put("T_COMMA", "','");
1658
                readableTokens.put("T_MAP", "'map'");
1659
                readableTokens.put("T_TO", "'to'");
1660
                readableTokens.put("T_QUANTITY", "'quantity'");
1661
                readableTokens.put("T_INFTY", "'inf'");
1662
                readableTokens.put("T_BOOL", "'bool'");
1663
                readableTokens.put("T_INT", "'int'");
1664
                readableTokens.put("T_RANGETO", "'..'");
1665
                readableTokens.put("T_FLOAT", "'float'");
1666
                readableTokens.put("T_FLOATNUMBER", "<floating point number>");
1667
                readableTokens.put("T_CHAR", "'char'");
1668
                readableTokens.put("T_CBRL", "'{'");
1669
                readableTokens.put("T_CBRR", "'}'");
1670
                readableTokens.put("T_AUTOCONS", "'autocons'");
1671
                readableTokens.put("T_VAR", "'var'");
1672
                readableTokens.put("T_METHODS", "'methods'");
1673
                readableTokens.put("T_ACTIONS", "'actions'");
1674
                readableTokens.put("T_DO", "'do'");
1675
                readableTokens.put("T_OD", "'od'");
1676
                readableTokens.put("T_STATIC", "'static'");
1677
                readableTokens.put("T_COLON", "':'");
1678
                readableTokens.put("T_END", "'end'");
1679
                readableTokens.put("T_CONT", "'cont'");
1680
                readableTokens.put("T_CTRL", "'ctr'");
1681
                readableTokens.put("T_OBS", "'obs'");
1682
                readableTokens.put("T_REQUIRES", "'requires'");
1683
                readableTokens.put("T_AND", "'and'");
1684
                readableTokens.put("T_ABORT", "'abort'");
1685
                readableTokens.put("T_SKIP", "'skip'");
1686
                readableTokens.put("T_KILL", "'kill'");
1687
                readableTokens.put("T_SELF", "'self'");
1688
                readableTokens.put("T_ASSIGNMENT", "':='");
1689
                readableTokens.put("T_WITH", "'with'");
1690
                readableTokens.put("T_IF", "'if'");
1691
                readableTokens.put("T_THEN", "'then'");
1692
                readableTokens.put("T_ELSE", "'else'");
1693
                readableTokens.put("T_FORALL", "'forall'");
1694
                readableTokens.put("T_EXISTS", "'exists'");
1695
                readableTokens.put("T_TRUE", "'true'");
1696
                readableTokens.put("T_FALSE", "'false'");
1697
                readableTokens.put("T_NIL", "'nil'");
1698
                readableTokens.put("T_STRINGLITERAL", "'\"<String>\"'");
1699
                readableTokens.put("T_NEW", "'new'");
1700
                readableTokens.put("T_BAR", "'|'");
1701
                readableTokens.put("T_MAPS", "'->'");
1702
                readableTokens.put("T_PRIMED", "'''");
1703
                readableTokens.put("T_POINT", "'.'");
1704
                readableTokens.put("T_NOTEQUAL", "'<>'");
1705
                readableTokens.put("T_SEQMOD_MAPOVERRIDE", "'++'");
1706
                readableTokens.put("T_BIIMPLIES", "'<=>'");
1707
                readableTokens.put("T_IMPLIES", "'=>'");
1708
                readableTokens.put("T_OR", "'or'");
1709
                readableTokens.put("T_ABS", "'abs'");
1710
                readableTokens.put("T_DIV", "'/'");
1711
                readableTokens.put("T_GREATER", "'>'");
1712
                readableTokens.put("T_GREATEREQUAL", "'>='");
1713
                readableTokens.put("T_IDIV", "'div'");
1714
                readableTokens.put("T_LESS", "'<'");
1715
                readableTokens.put("T_LESSEQUAL", "'<='");
1716
                readableTokens.put("T_MINUS", "'-'");
1717
                readableTokens.put("T_MOD", "'mod'");
1718
                readableTokens.put("T_POW", "'**'");
1719
                readableTokens.put("T_PROD", "'*'");
1720
                readableTokens.put("T_SUM", "'+'");
1721
                readableTokens.put("T_CONC", "'^'");
1722
                readableTokens.put("T_DIFF", "'\\'");
1723
                readableTokens.put("T_INTER", "'inter'");
1724
                readableTokens.put("T_IN", "'in'");
1725
                readableTokens.put("T_SET", "'set'");
1726
                readableTokens.put("T_NOT", "'not'");
1727
                readableTokens.put("T_SUBSET", "'subset'");
1728
                readableTokens.put("T_UNION", "'union'");
1729
                readableTokens.put("T_DOMRESBY", "'<-:'");
1730
                readableTokens.put("T_DOMRESTO", "'<:'");
1731
                readableTokens.put("T_RNGRESBY", "':->'");
1732
                readableTokens.put("T_RNGRESTO", "':>'");
1733
                readableTokens.put("T_MUNION", "'munion'");
1734
                readableTokens.put("T_CARD", "'card'");
1735
                readableTokens.put("T_DCONC", "'conc'");
1736
                readableTokens.put("T_DINTER", "'dinter'");
1737
                readableTokens.put("T_DUNION", "'dunion'");
1738
                readableTokens.put("T_ELEMS", "'elems'");
1739
                readableTokens.put("T_HEAD", "'hd'");
1740
                readableTokens.put("T_INDS", "'inds'");
1741
                readableTokens.put("T_LEN", "'len'");
1742
                readableTokens.put("T_TAIL", "'tl'");
1743
                readableTokens.put("T_DOM", "'dom'");
1744
                readableTokens.put("T_RNG", "'rng'");
1745
                readableTokens.put("T_MERGE", "'merge'");
1746
                readableTokens.put("T_WS", "<space>");
1747
                readableTokens.put("T_COMMENT", "'/*<comment>*/'");
1748
                readableTokens.put("LINE_COMMENT", "'#<line comment>'");
1749
                readableTokens.put("T_DIGIT", "<0..9>");
1750
                readableTokens.put("FLOAT_OR_INT_OR_RANGE", "<float_int_range>");
1751
                readableTokens.put("T_LETTER", "<a..z,A..Z>");
1752
                readableTokens.put("'|['", "'|['");
1753
                readableTokens.put("']|'", "']|'");
1754
                readableTokens.put("'add'", "'add'");
1755
                readableTokens.put("'mult'", "'mult'");
1756
                readableTokens.put("'deriv'", "'deriv'");
1757
                readableTokens.put("'mon+'", "'mon+'");
1758
                readableTokens.put("'mon-'", "'mon-'");
1759
                readableTokens.put("'id'", "'id'");
1760
                readableTokens.put("'qval'", "'qval'");
1761
                readableTokens.put("'\"'", "'\"'");
1762
                readableTokens.put("as", "as");
1763
        }
1764

    
1765
        /* override routine that displays recongition errors.. */
1766
        @Override
1767
        public void displayRecognitionError(String[] tokenNames, RecognitionException e)
1768
        {
1769
                int i;
1770
                final StringBuilder result = new StringBuilder();
1771
//                SetUpTokenDictionary();
1772

    
1773

    
1774
                if (e instanceof MismatchedTokenException)
1775
                {
1776
                        result.append("Found '");
1777
                        result.append(e.token.getText());
1778
                        result.append("'");
1779
                        i = ((MismatchedTokenException)e).expecting;
1780
                        result.append(" Expected: ");
1781
                        result.append(readableTokens.get(tokenNames[i]));
1782
                        result.append(" ("); result.append(tokenNames[i]); result.append(") ");
1783

    
1784
                }
1785
                else
1786
                {
1787
                        /*if (e is NoViableAltException)
1788
            {
1789
                result.Append("Unexpected '");
1790
                result.Append(e.Token.getText());
1791
                result.Append("' (");
1792
                i = ((NoViableAltException)e).UnexpectedType;
1793
                result.Append(tokenNames[i]);
1794
                result.Append(")");
1795
            }
1796
            else*/
1797
                        if (e instanceof RecognitionException)
1798
                        {
1799
                                result.append("Unexpected '");
1800
                                result.append(e.token.getText());
1801
                                result.append("' (");
1802
                                i = e.getUnexpectedType();
1803
                                result.append(tokenNames[i]);
1804
                                result.append(") ");
1805
                        }
1806
                        else
1807
                                result.append(e.getMessage());
1808
                }
1809

    
1810
                pState.AddErrorMessage(new ParserError(pState.filename, e.line, e.charPositionInLine, result.toString()));
1811
        }
1812

    
1813

    
1814
        /* just run over once */
1815
        public static int FirstPass(ParserState pState)
1816
        {
1817
                pState.parser.ooActionSystems();
1818

    
1819
                return pState.listOfParserErrors.size(); // + pState.lexer.NumberOfSyntaxErrors;
1820
        }
1821

    
1822

    
1823

    
1824
        /* print syntax tree */
1825
        public static String PrintSyntaxTree(ParserState pState)
1826
        {
1827
                if ((pState != null) && (pState.ooaSystem != null))
1828
                {
1829
                        return pState.ooaSystem.toString();
1830
                }
1831
                else
1832
                        return "";
1833
        }
1834

    
1835

    
1836
        public ooaCustomParser(TokenStream input, RecognizerSharedState state) {
1837
                super(input, state);
1838
        }
1839
}