Project

General

Profile

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

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
                        if (aType.kind() != TypeKind.QrType)
465
                                doError(varname, "'obs' or 'ctr' on attributes only allowed for qualitative types");
466

    
467

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

    
475

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
696
                return result;
697
        }
698

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

    
706
                int numElems = 0;
707

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

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

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

    
743
                int max = 0;
744

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

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

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

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

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

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

    
799

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

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

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

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

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

    
827

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

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

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

    
840

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

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

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

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

    
861

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

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

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

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

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

    
887
                newMethod.SetBody(statements);
888
        }
889

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

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

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

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

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

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

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

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

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

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

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

    
964
                top.AddStatement(stmt);
965
        }
966

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

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

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

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

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

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

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

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

    
1014

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

    
1021

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

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

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

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

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

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

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

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

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

    
1094

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

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

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

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

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

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

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

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

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

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

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

    
1156

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

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

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

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

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

    
1218

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

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

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

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

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

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

    
1272

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

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

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

    
1295

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

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

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

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

    
1332

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

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

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

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

    
1361
                return result;
1362
        }
1363

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

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

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

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

    
1396

    
1397

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1554

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

    
1562

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

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

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

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

    
1590

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

    
1596

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

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

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

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

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

    
1629
        /* ====== */
1630
        /* ====== */
1631

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

    
1634

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

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

    
1774

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

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

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

    
1814

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

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

    
1823

    
1824

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

    
1836

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