Project

General

Profile

Revision 7

Added by Willibald K. over 8 years ago

changing java, cpp, hpp files to unix line endings

View differences:

ooaCustomParser.java
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
  */

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 26

  
27 27

  
28
package org.momut.ooas.parser;
29

  
30
import java.util.LinkedHashMap;
31
import java.util.LinkedList;
32
import java.util.List;
28
package org.momut.ooas.parser;
33 29

  
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;
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 40
import org.momut.ooas.ast.IScope;
41 41
import org.momut.ooas.ast.expressions.AccessExpression;
42 42
import org.momut.ooas.ast.expressions.BinaryOperator;
......
110 110
import org.momut.ooas.utils.exceptions.ArgumentException;
111 111
import org.momut.ooas.utils.exceptions.NotImplementedException;
112 112
import org.momut.ooas.visitors.OoaResolveExpressionsVisitor;
113

  
114
public class ooaCustomParser extends Parser
115
{
116
	public ParserState pState;
117

  
118

  
119
	public boolean IsRightToLeft(ExpressionKind type)
120
	{
121
		return type == ExpressionKind.implies; // implication has right grouping
122
	}
123

  
124
	public int GetOperatorPrecedence(ExpressionKind type)
125
	{
126
		switch (type)
127
		{
128
		/*Family of Evaluators*/
129

  
130
		case abs:    // T_ABS:
131
		case card:   // T_CARD:
132
		case dom:    // T_DOM:
133
		case range:  // T_RNG:
134
		case merge:  // T_MERGE:
135
		case len:    // T_LEN:
136
		case elems:  // T_ELEMS:
137
		case head:   // T_HEAD:
138
		case tail:   // T_TAIL:
139
		case conc:   // T_CONC:
140
		case inds:   // T_INDS:
141
		case dinter: // T_DINTER:
142
		case dunion: // T_DUNION:
143
			return 1;
144

  
145
		case domresby:   // T_DOMRESBY:
146
		case domresto:   // T_DOMRESTO:
147
		case rngresby:   // T_RNGRESBY:
148
		case rngresto:   // T_RNGRESTO:
149
			return 2;
150

  
151
		case div:    // T_DIV:
152
		case idiv:   // T_IDIV:
153
		case mod:    // T_MOD:
154
		case prod:   // T_PROD:
155
		case inter:  // T_INTER:
156
			return 3;
157

  
158
		case sum:    // T_SUM:
159
		case minus:  // T_MINUS:
160
		case union:  // T_UNION:
161
		case diff:   // T_DIFF:
162
		case munion: // T_MUNION:
163
		case seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
164
			return 4;
165

  
166
			/*Family of Relations*/
167

  
168
		case less:
169
		case lessequal:
170
		case greater:
171
		case greaterequal:
172
		case equal:
173
		case notequal:
174
		case subset:
175
		case elemin:
176
		case notelemin:
177
			return 5;
178

  
179
			/*Family of Connectives*/
180

  
181
		case and:    // T_AND:
182
			return 6;
183

  
184
		case or:     // T_OR:
185
			return 7;
186

  
187
		case implies:    // T_IMPLIES:
188
			return 8;
189

  
190
		case biimplies:  // T_BIIMPLIES:
191
			return 9;
192

  
193
		default:
194
			throw new NotImplementedException("operator not supported: " + type.toString());
195
			// return 0;
196
		}
197
	}
198

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

  
221
	Expression createPrecedenceTree(
222
			List<Expression> expressions,
223
			List<BinaryOperator> operators,
224
			int startIndex,
225
			int stopIndex)
226
	{
227
		if (stopIndex == startIndex)
228
			return expressions.get(startIndex);
229

  
230
		final int pivot = findPivot(operators, startIndex, stopIndex - 1);
231

  
232
		final BinaryOperator result = operators.get(pivot);
233
		result.SetLeftChild(createPrecedenceTree(expressions, operators, startIndex, pivot));
234
		result.SetRightChild(createPrecedenceTree(expressions, operators, pivot + 1, stopIndex));
235
		return result;
236
	}
237

  
238
	Expression createPrecedenceTree(List<Expression> expressions, List<BinaryOperator> operators)
239
	{
240
		return createPrecedenceTree(expressions, operators, 0, expressions.size() - 1);
241
	}
242

  
243

  
244
	/* add error message to state. */
245
	private void doError(Token aToken, String aMessage)
246
	{
247
		pState.AddErrorMessage(
248
				new ParserError(pState.filename, aToken, aMessage));
249
	}
250

  
251
	/* add warning message to state */
252
	private void doWarning(Token id1, String p)
253
	{
254
		pState.AddWarningMessage(new ParserWarning(pState.filename, id1, p));
255
	}
256

  
257
	private void doError(String aMessage)
258
	{
259
		pState.AddErrorMessage(
260
				new ParserError(pState.filename, 0, 0, aMessage));
261
	}
262

  
263
	/* init global state */
264
	 void initializeTopLevelParserState()
265
	{
266
		pState.ooaSystem = new MainModule();
267
		pState.PushResolveStack(pState.ooaSystem);
268
	}
269

  
270

  
271
	private IScope GetScope()
272
	{
273
		return pState.currentScope;
274
	}
275

  
276

  
277
	/*create a named constant*/
278
	 void addNamedConst(Token aName, Expression anExpr)
279
	{
280
		if (pState.currentScope.ResolveIdentifier(aName.getText()) == null)
281
		{
282
			/* needs to be a constant... */
283
			final ConstantIdentifier aConst = new ConstantIdentifier(aName, anExpr, GetScope());
284

  
285
			final OoaResolveExpressionsVisitor resolver = new OoaResolveExpressionsVisitor(pState);
286
			aConst.Accept(resolver);
287

  
288
			if (aConst.Value() == null || aConst.Value().type() == null || aConst.Value().kind() != ExpressionKind.Value)
289
			{
290
				doError(aName, String.format("%s not a constant!", aName.getText()));
291
			}
292
			else
293
			{
294
				aConst.SetType(aConst.Value().type());
295
				pState.currentScope.AddIdentifier(aConst, null);
296
			}
297
		}
298
		else
299
			doError(aName, String.format("%s already defined!", aName.getText()));
300
	}
301

  
302

  
303

  
304
	/* create a named type; we're on top-level here */
305
	 void createNamedType(Token aName, UlyssesType aType)
306
	{
307
		// precond..
308
		assert(aName != null);
309

  
310
		if (aType == null)
311
		{
312
			doError(aName, String.format("%s lacks a type! (Type not added)", aName.getText()));
313
			return;
314
		}
315

  
316

  
317
		if (pState.currentScope.ResolveIdentifier(aName.getText()) == null)
318
		{
319
			final TypeIdentifier newid = new TypeIdentifier(aName, aType, GetScope());
320
			aType.SetTypeIdentifier(newid);
321
			pState.currentScope.AddIdentifier(newid, null);
322
		}
323
		else
324
			doError(aName, String.format("%s already defined!", aName.getText()));
325

  
326
	}
327

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

  
348
		final OoActionSystemType result = new OoActionSystemType(autoCons, refinedSystemType, null);
349

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

  
353
		pState.PushResolveStack(result);
354
		return result;
355
	}
356

  
357
	/* remove ooa-system symbols from resolve stack TOS */
358
	void fixupOoaType(OoActionSystemType aTypeSymbol)
359
	{
360
		if (aTypeSymbol == null)
361
			return;
362

  
363
		aTypeSymbol.SetupAnonymousName();
364
		if (aTypeSymbol != null)
365
			pState.PopResolveStack();
366
	}
367

  
368
	Expression addCastExpression(Expression e, Token cid)
369
	{
370
		assert(e != null);
371

  
372
		final Expression result = new UnaryOperator(ExpressionKind.Cast, e, cid.getLine(), cid.getCharPositionInLine());
373
		result.SetType(new OpaqueType(new TypeIdentifier(cid, null, GetScope())));
374
		pState.typesToFixUp.add((OpaqueType)result.type());
375
		return result;
376
	}
377

  
378

  
379
	/* add a new ooa to the list describing the composition of action systems */
380
	 void addToIdentifierList(IdentifierList top, Token aName)
381
	{
382
		assert(top != null);
383

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

  
404
	/* does a fixup run after parsing */
405
	 void fixUpRun(IdentifierList sysDescr)
406
	{
407
		// set system descr.
408
		pState.ooaSystem.SetSystemDescription(sysDescr);
409

  
410
		// fixup named types
411
		FixupNamedTypes();
412
	}
413

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

  
437

  
438
	private boolean TosIsActionSystem()
439
	{
440
		return pState.currentScope instanceof OoActionSystemType;
441
	}
442

  
443

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

  
450
	private int currentPos()
451
	{
452
		final Token token = input.LT(-1);
453
		return token == null ? 0 : token.getCharPositionInLine();
454
	}
455

  
456
	/* add var symbol to the current action system */
457
	void createAttribute(Token varname, boolean isStatic, boolean isObs, boolean isCtr, UlyssesType aType, Expression anExpr)
458
	{
459
		if (!TosIsActionSystem())
460
			return;
461

  
462
		if (aType == null)
463
		{
464
			doError(varname, String.format("%s lacks type!", varname.getText()));
465
		}
466
		if (anExpr == null)
467
		{
468
			doError(varname, String.format("%s lacks initializer!", varname.getText()));
469
		}
470
		if (isObs == true || isCtr == true)
471
			if (aType.kind() != TypeKind.QrType)
472
				doError(varname, "'obs' or 'ctr' on attributes only allowed for qualitative types");
473

  
474

  
475
		final AttributeIdentifier var = new AttributeIdentifier(varname, aType, GetScope(), anExpr, isStatic, isObs, isCtr);
476
		if (pState.currentScope.ResolveIdentifier(varname.getText()) == null)
477
			pState.currentScope.AddIdentifier(var, null);
478
		else
479
			doError(varname, String.format("Can not add %s: Symbol already defined!", varname.getText()));
480
	}
481

  
482

  
483
	/* create a boolean type */
484
	BoolType createBoolType()
485
	{
486
		return new BoolType(null);
487
	}
488

  
489
	/* create a char type */
490
	CharType createCharType()
491
	{
492
		return new CharType(null);
493
	}
494

  
495
	/* create an int type */
496
	@SuppressWarnings("unchecked")
497
	UlyssesType createIntType(Token rangeLow, Token rangeHigh)
498
	{
499
		int low = 0;
500
		int high = 0;
501

  
502
		if (rangeLow.getType() == ooaLexer.T_INFTY)
503
			doError(rangeLow, "Infinity not supported.");
504
		if (rangeLow.getType() == ooaLexer.T_INFTY)
505
			doError(rangeHigh, "Infinity not supported.");
506

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

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

  
543
		if (high < low)
544
			doError(rangeHigh, "Lower bound greater than upper bound");
545

  
546
		return new IntType(low, high, null);
547
	}
548

  
549
	/* create a float type */
550
	 @SuppressWarnings("unchecked")
551
	UlyssesType createFloatType(Token rangeLow, Token rangeHigh)
552
	{
553
		float low = 0;
554
		float high = 0;
555

  
556
		if (rangeLow.getType() == ooaLexer.T_INFTY)
557
			doError(rangeLow, "Infinity not supported.");
558
		if (rangeLow.getType() == ooaLexer.T_INFTY)
559
			doError(rangeHigh, "Infinity not supported.");
560

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

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

  
597
		if (high < low)
598
			doError(rangeHigh, "Lower bound greater than upper bound");
599

  
600
		/* precision */
601
		final float afterc_low = low -  (float)Math.floor(low); //(float)Convert.ToInt32(low);
602
		final float afterc_high = high - (float)Math.floor(high); //(float)Convert.ToInt32(high);
603
		final float precision = afterc_low < afterc_high ? afterc_low : afterc_high;
604

  
605
		return new FloatType(low, high, precision, null);
606
	}
607

  
608
	/* create a list of an enumerated type */
609
	 UlyssesType createListEnumType(Token alistelem)
610
	{
611
		final EnumType hiddenEnumType = new EnumType(null);
612

  
613
		final ListType result = new ListType(hiddenEnumType, 500, null);
614
		addToListEnumType(result, alistelem);
615
		return result;
616
	}
617

  
618
	/* add a new enum symbol to a list with an anonymous enumerated type */
619
	 void addToListEnumType(UlyssesType aTypeSymbol, Token otherlistelem)
620
	{
621
		final EnumType enumtype = (EnumType)((ListType)aTypeSymbol).innerType();
622
		addToEnumType(enumtype, otherlistelem, null);
623
	}
624

  
625
	/* create a new enumerated type */
626
	 UlyssesType createEnumType(Token aRangeValue, Token anIntegerValue)
627
	{
628
		EnumType result;
629

  
630
		if (anIntegerValue == null)
631
			result = new EnumType(null);
632
		else
633
			result = new ValuedEnumType(null);
634

  
635
		addToEnumType(result, aRangeValue, anIntegerValue);
636
		return result;
637
	}
638

  
639
	/* add a new enum symbol to the enumerated type */
640
	 void addToEnumType(UlyssesType aTypeSymbol, Token otherRangeValue, Token anIntegerValue)
641
	{
642
		final EnumType anEnum = (EnumType)aTypeSymbol;
643
		if (anEnum.symbolTable().Defined(otherRangeValue.getText()))
644
		{
645
			doError(otherRangeValue, String.format("Element '%s' already defined!", otherRangeValue.getText()));
646
			return;
647
		}
648

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

  
660
		EnumIdentifier enumval;
661
		if (anIntegerValue == null)
662
		{
663
			if (aTypeSymbol instanceof ValuedEnumType)
664
			{
665
				doError(otherRangeValue, String.format("Element '%s' needs integer value!", otherRangeValue.getText()));
666
				return;
667
			}
668

  
669
			enumval = new EnumIdentifier(otherRangeValue, (EnumType)aTypeSymbol, GetScope());
670
		}
671
		else
672
		{
673
			if (!(aTypeSymbol instanceof ValuedEnumType))
674
			{
675
				doError(otherRangeValue, String.format("Element '%s' must not have integer value!", otherRangeValue.getText()));
676
				return;
677
			}
678
			enumval = new EnumIdentifier(otherRangeValue, Integer.parseInt(anIntegerValue.getText()), (EnumType)aTypeSymbol, GetScope());
679
		}
680

  
681
		((EnumType)aTypeSymbol).AddEnumSymbol(enumval);
682

  
683
		/* add the enum id to 'global' state */
684
		pState.currentScope.AddIdentifier(enumval, null);
685
	}
686

  
687
	/* get a named type */
688
	 UlyssesType getNamedType(Token aType)
689
	{
690
		UlyssesType result = null;
691
		final Identifier sym = pState.Lookup(aType);
692
		if (sym == null)
693
		{
694
			/* we might not have seen this type yet - so do a fixup run later */
695
			result = new OpaqueType(new TypeIdentifier(aType, null, GetScope()));
696
			pState.typesToFixUp.add((OpaqueType)result);
697
		}
698
		else if (sym.kind() == IdentifierKind.TypeIdentifier)
699
			result = ((TypeIdentifier)sym).type();
700
		else
701
			doError(aType, "Not a named type symbol: " + aType.getText());
702

  
703
		return result;
704
	}
705

  
706
	/* create a list type */
707
	 @SuppressWarnings("unchecked")
708
	UlyssesType createListType(Token numOfElements, UlyssesType innertype)
709
	{
710
		if (innertype == null)
711
			doError(numOfElements, "List type lacks proper element type (null)");
712

  
713
		int numElems = 0;
714

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

  
737
		final ListType result = new ListType(innertype, numElems, null);
738
		return result;
739
	}
740

  
741
	/* create a map type */
742
	 @SuppressWarnings("unchecked")
743
	UlyssesType createMapType(Token numOfElements, UlyssesType mapfromtype, UlyssesType maptotype)
744
	{
745
		if (mapfromtype == null)
746
			doError(numOfElements, "Map: From-type not set (null)");
747
		if (maptotype == null)
748
			doError(numOfElements, "Map: To-type not set (null)");
749

  
750
		int max = 0;
751

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

  
770
		final MapType result = new MapType(mapfromtype, maptotype, max, null);
771
		return result;
772
	}
773

  
774
	/* create a tuple type */
775
	 UlyssesType createTupleType(UlyssesType aType)
776
	{
777
		final TupleType result = new TupleType(null);
778
		addToTupleType(result, aType);
779
		return result;
780
	}
781

  
782
	/* add inner type to tuple */
783
	 void addToTupleType(UlyssesType aTypeSymbol, UlyssesType anotherType)
784
	{
785
		final TupleType tuple = (TupleType)aTypeSymbol;
786
		if (anotherType != null)
787
			tuple.AddType(anotherType);
788
		else
789
			doError("Unknown inner type in tuple");
790
	}
791

  
792
	/* create a QR type */
793
	UlyssesType createQrType(Token alandmark)
794
	{
795
		final QrType result = new QrType(null);
796
		addToQrType(result, alandmark);
797
		return result;
798
	}
799

  
800
	/* add another landmark to QR type */
801
	protected void addToQrType(UlyssesType aTypeSymbol, Token otherlandmark)
802
	{
803
		final Identifier sym = pState.Lookup(otherlandmark);
804
		if (sym != null)
805
		{
806
			doError(otherlandmark, String.format("Redifinition of %s", otherlandmark.getText()));
807
			return;
808
		}
809

  
810
		final LandmarkIdentifier lndmrk = new LandmarkIdentifier(otherlandmark, (QrType)aTypeSymbol, GetScope());
811
		((QrType)aTypeSymbol).AddLandmark(lndmrk);
812
	}
813

  
814
	/* gets called after a simple type has been constructed. used to define an internal name*/
815
	 void fixupSimpleType(UlyssesType aTypeSymbol)
816
	{
817
		if (aTypeSymbol != null)
818
			aTypeSymbol.SetupAnonymousName();
819
	}
820

  
821
	/* gets called after a simple or complex type has been constructed. used to define an internal name */
822
	 void fixupComplexType(UlyssesType aTypeSymbol)
823
	{
824
		if (aTypeSymbol != null)
825
			aTypeSymbol.SetupAnonymousName();
826
	}
827

  
828

  
829
	/* create a method symbol */
830
	 FunctionIdentifier createMethodSymbol(Token mname)
831
	{
832
		final Identifier sym = pState.Lookup(mname);
833
		if (sym != null)
834
		{
835
			doError(mname, String.format("Redefinition of %s", mname.getText()));
836
			return null;
837
		}
838

  
839
		final FunctionType funtype = new FunctionType(FunctionTypeEnum.Method, new LinkedList<UlyssesType>(), null);
840
		final MethodIdentifier msym = new MethodIdentifier(mname, funtype, GetScope());
841
		// funtype.SetTypeIdentifier(msym); -- the type of this function doesn't have a name!
842

  
843
		pState.currentScope.AddIdentifier(msym, null);
844

  
845
		pState.PushResolveStack(msym);
846
		return msym;
847
	}
848

  
849
	/* remove local method symbols from resolution stack again */
850
	protected void popResolveStack(FunctionIdentifier newMethod)
851
	{
852
		if (newMethod != null)
853
			pState.PopResolveStack();
854
	}
855

  
856

  
857
	/* add a return type to a method */
858
	 void setMethodReturnType(FunctionIdentifier newMethod, UlyssesType rt)
859
	{
860
		if (newMethod == null)
861
			return;
862

  
863
		if (rt == null)
864
			doError(String.format("Method %s has no return type (null)", newMethod.tokenText()));
865

  
866
		/* set return type */
867
		((FunctionType)newMethod.type()).SetReturnType(rt);
868

  
869

  
870
		/* add hidden return parameter */
871
		if (newMethod.symbolTable().Defined("result"))
872
		{
873
			doError(String.format("Method %s defines 'result'", newMethod.tokenText()));
874
			return;
875
		}
876

  
877
		final ParameterIdentifier returnval = new ParameterIdentifier("result", rt, GetScope());
878
		newMethod.symbolTable().AddIdentifier(returnval);
879
	}
880

  
881
	/* add a parameter to a method */
882
	 void addMethodParameter(FunctionIdentifier newMethod, Token paramName, UlyssesType atype)
883
	{
884
		if (newMethod == null)
885
			return;
886

  
887
		if (atype == null)
888
			doError(paramName, "Parameter has no type (null)");
889

  
890

  
891
		if (newMethod.symbolTable().Defined(paramName.getText()) == true)
892
		{
893
			doError(paramName, String.format("Parameter '%s' already defined", paramName.getText()));
894
			return;
895
		}
896

  
897
		// add parameter to scope
898
		final ParameterIdentifier param = new ParameterIdentifier(paramName, atype, GetScope());
899
		newMethod.AddParameter(param);
900

  
901
		// add type of param to signature
902
		final FunctionType ftype = (FunctionType)newMethod.type();
903
		ftype.AddParameterType(atype);
904
	}
905

  
906
	/* set method body of a method */
907
	 void addMethodBody(FunctionIdentifier newMethod, Block statements)
908
	{
909
		if (newMethod == null)
910
			return;
911

  
912
		if (statements == null)
913
			doError(String.format("%s has empty body (null)",
914
					((FunctionType)newMethod.type()).functionType() == FunctionTypeEnum.Method ? "Method" : "Action"));
915

  
916
		newMethod.SetBody(statements);
917
	}
918

  
919
	/* create a continuous action */
920
	 FunctionIdentifier createNamedContinuousAction(Token cactionname, FunctionTypeEnum actionTypeEnum)
921
	{
922
		return createNamedAction(cactionname, actionTypeEnum);
923
	}
924

  
925
	/* create a named action */
926
	 FunctionIdentifier createNamedAction(Token actionname, FunctionTypeEnum actionType)
927
	{
928
		final Identifier sym = pState.Lookup(actionname);
929
		if (sym != null)
930
		{
931
			doError(actionname, String.format("Symbol '%s' already defined.", sym.tokenText()));
932
			return null;
933
		}
934

  
935
		final FunctionType atype = new FunctionType(actionType, new LinkedList<UlyssesType>(), null);
936
		final NamedActionIdentifier action = new NamedActionIdentifier(actionname, atype, GetScope());
937
		// atype.SetTypeIdentifier(action); -- the type of this action doesn't have a name!
938

  
939
		pState.currentScope.AddIdentifier(action, null);
940
		pState.PushResolveStack(action);
941
		return action;
942
	}
943

  
944
	/* add body of action */
945
	 void addActionBody(FunctionIdentifier newAction, GuardedCommand body)
946
	{
947
		// we need a wrapper around the guarded command..
948
		final Block bdy = new SeqBlock(currentLine(), currentPos());
949
		addMethodBody(newAction, bdy);
950
		body.SetParentScope(bdy);
951
		bdy.AddStatement(body);
952
	}
953

  
954
	/* add constraints of cont. action */
955
	 void addContinuousActionBody(FunctionIdentifier newAction, GuardedCommand constraints)
956
	{
957
		final Block bdy = new SeqBlock(currentLine(), currentPos());
958
		bdy.AddStatement(constraints);
959
		addMethodBody(newAction, bdy);
960
	}
961

  
962
	/* create a guarded command */
963
	 GuardedCommand createGuardedCommandStatement()
964
	 {
965
		 return new GuardedCommand(null, null, currentLine(), currentPos());
966
	 }
967

  
968
	 void addExprAndBlockToGuardedCommand(GuardedCommand cmd, Expression expr, Block bdy)
969
	{
970
		if (bdy == null)
971
			doError("Guarded command without body (null)!");
972

  
973
		if (expr == null)
974
			doError("Guarded command without guard (null)!");
975

  
976
		cmd.SetGuard(expr);
977
		cmd.SetBody(bdy);
978
	}
979
	 GuardedCommand createGuardedCommandStatement(Expression expr, Block bdy, boolean isQualitative)
980
	{
981
		final GuardedCommand result = createGuardedCommandStatement();
982
		addExprAndBlockToGuardedCommand(result, expr, bdy);
983
		result.SetIsQualitative(isQualitative);
984
		return result;
985
	}
986

  
987
	/* add statements to list */
988
	 void addToStatementList(Block top, Statement stmt)
989
	{
990
		if (stmt == null)
991
			doError("Can not add statement: null!");
992

  
993
		top.AddStatement(stmt);
994
	}
995

  
996
	/* create a Kill statement */
997
	 Statement createKillStatement(Token aname)
998
	{
999
		final Identifier sym = pState.Lookup(aname);
1000
		if (sym == null)
1001
			doError(aname, "Not defined");
1002

  
1003
		final KillStatement result = new KillStatement(sym, aname.getLine(), aname.getCharPositionInLine());
1004
		return result;
1005
	}
1006

  
1007
	/* create a Skip statement */
1008
	 Statement createSkipStatement()
1009
	{
1010
		return new SkipStatement(currentLine(), currentPos());
1011
	}
1012

  
1013
	/* create a Break statement */
1014
	 Statement createBreakStatement()
1015
	{
1016
		return new BreakStatement(currentLine(), currentPos());
1017
	}
1018

  
1019
	/* create an Abort statement */
1020
	 Statement createAbortStatement()
1021
	{
1022
		return new AbortStatement(currentLine(), currentPos());
1023
	}
1024

  
1025
	/* creates a prioritized composition block */
1026
	 Block createPrioBlock(Block top)
1027
	{
1028
		return new PrioBlock(top, currentLine(), currentPos());
1029
	}
1030

  
1031
	/* creates a nondeterministically composed block */
1032
	 Block createNondetBlock(Block top)
1033
	{
1034
		return new NondetBlock(top, currentLine(), currentPos());
1035
	}
1036

  
1037
	/* creates a sequentially composed block */
1038
	 SeqBlock createSeqBlock(Block top)
1039
	{
1040
		return new SeqBlock(top, currentLine(), currentPos());
1041
	}
1042

  
1043

  
1044
	/* adds a filter expression to seq block */
1045
	protected void addSeqBlockExpression(Block seqList, Expression sexpr)
1046
	{
1047
		seqList.SetFilter(sexpr); /*gets transformed to guarded command in resolvevisitor!*/
1048
	}
1049

  
1050

  
1051
	/* create a self identifier */
1052
	 IdentifierExpression createSelfIdentifierExpression(Token self)
1053
	{
1054
		final Identifier id = pState.Lookup("self");
1055
		if (id == null)
1056
		{
1057
			doError(self, "Can not resolve 'self'");
1058
			return null;
1059
		}
1060

  
1061
		final IdentifierExpression result = new IdentifierExpression(id, self.getLine(), self.getCharPositionInLine());
1062
		result.setIsSelf(true);
1063
		return result;
1064
	}
1065

  
1066
	/* build up identifier tree... */
1067
	 Expression createIdentifierAccessExpression(IdentifierExpression aself, Token token)
1068
	{
1069
		final Identifier someid = pState.Lookup(token.getText(), GetScope());
1070
		final Identifier self = pState.Lookup("self");
1071

  
1072
		if (someid != null)
1073
		{
1074
			switch (someid.kind())
1075
			{
1076
			/* all method and attribute accesses are prefixed by self */
1077
			case AttributeIdentifier:
1078
			case MethodIdentifier:
1079
				if (self == null)
1080
					doError(token, "Self access of method: Can not find 'self' symbol! (internal error)");
1081
				aself = new IdentifierExpression(self, token.getLine(), token.getCharPositionInLine());
1082
				aself.setIsSelf(true);
1083
				break;
1084
			default:
1085
				break;
1086
			}
1087
		}
1088

  
1089
		final IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
1090
		if (aself != null)
1091
			return new AccessExpression(aself, ident, token.getLine(), token.getCharPositionInLine());
1092
		else
1093
			return ident;
1094
	}
1095

  
1096
	 AccessExpression addIdentifierAccessExpression(Expression parent, Token token)
1097
	{
1098
		final IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
1099
		return new AccessExpression(parent, ident, token.getLine(), token.getCharPositionInLine());
1100
	}
1101

  
1102
	/* we have a primed id; prime the complete subtree.. */
1103
	Expression setIdentifierExpressionPrimed(Expression oldExpr, Token token)
1104
	{
1105
		return new UnaryOperator(ExpressionKind.Primed, oldExpr, token.getLine(), token.getCharPositionInLine());
1106
	}
1107

  
1108
	/* create a fold operation */
1109
	 Expression createFoldExpression(Expression result, Token afold, Expression initval, Expression anexpr)
1110
	{
1111
		ExpressionKind akind = ExpressionKind.foldLR;
1112
		if (afold.getType() == ooaLexer.T_FOLDLR)
1113
			akind = ExpressionKind.foldLR;
1114
		else if (afold.getType() == ooaLexer.T_FOLDRL)
1115
			akind = ExpressionKind.foldRL;
1116
		else
1117
			assert(false);
1118

  
1119
		final TernaryOperator op = new TernaryOperator(akind, result, initval, anexpr, currentLine(), currentPos(), GetScope());
1120
		return op;
1121
	}
1122

  
1123

  
1124
	/* create a method access */
1125
	 CallExpression createMethodAccessExpression(Expression subexpr, List<Expression> m_params, Token token)
1126
	{
1127
		assert(subexpr != null);
1128

  
1129
		return new CallExpression(subexpr, m_params, token.getLine(), token.getCharPositionInLine(), GetScope());
1130
	}
1131

  
1132
	/* create a tuple or map access */
1133
	 TupleMapAccessExpression createTupleMapAccessExpression(Expression subexpr, Expression ac, Token token)
1134
	{
1135
		assert(subexpr != null);
1136

  
1137
		return new TupleMapAccessExpression(subexpr, ac, token.getLine(), token.getCharPositionInLine());
1138
	}
1139

  
1140
	/* create a method call statement; has to be resolved in a second run */
1141
	 Statement createCallStatement(Expression aqname)
1142
	{
1143
		return new Call(aqname, currentLine(), currentPos());
1144
	}
1145

  
1146
	/* create a single assignment statement */
1147
	 Statement createSingleAssignmentStatement(Expression aqname, Expression aexp)
1148
	{
1149
		final Assignment result = new Assignment(aqname, aexp, null, currentLine(), currentPos());
1150
		return result;
1151
	}
1152

  
1153
	/* create a multi-assignment statement; has to be resolved in a second run */
1154
	 Statement createMultipleAssignmentStatementLHS(Expression aqname)
1155
	{
1156
		return new Assignment(aqname, null, null, currentLine(), currentPos());
1157
	}
1158

  
1159
	/* adds an expression to the multi-assign */
1160
	 void addMutlipleAssignmentStatementRHS(Statement result, Expression mexp)
1161
	{
1162
		((Assignment)result).AddValue(mexp);
1163
	}
1164

  
1165
	/* adds a LHS-var to the multi assign */
1166
	 void addMultipleAssignmentStatementLHS(Statement result, Expression malhs)
1167
	{
1168
		((Assignment)result).AddPlace(malhs);
1169
	}
1170

  
1171
	/* pop an assignment statement from the resolve stack */
1172
	 void popAssignmentOffResolveStack(Statement result)
1173
	{
1174
		assert(result == pState.currentScope); // ref eq.
1175
		pState.PopResolveStack();
1176
	}
1177

  
1178
	/* pushes the assignment statement onto resolve stack. */
1179
	 void pushAssignmentOnResolveStack(Statement result)
1180
	{
1181
		assert(result instanceof Assignment);
1182
		pState.PushResolveStack((Assignment)result);
1183
	}
1184

  
1185

  
1186
	/* adds a nondet-assignment constraint */
1187
	 void addConstraintToAssignment(Statement result, Expression ndexp)
1188
	{
1189
		((Assignment)result).SetNondetExpression(ndexp);
1190
	}
1191

  
1192
	/* add a named action call to do-od block */
1193
	 void addNamedActionCallToBlockList(Block top, Token aname, List<Expression> m_params, Token maptoken, Expression amapexpression)
1194
	{
1195
		final Identifier id = pState.Lookup(aname);
1196
		if (id == null)
1197
		{
1198
			doError(aname, String.format("Could not find named action '%s'", aname.getText()));
1199
			return;
1200
		}
1201
		Expression callexpr;
1202
		if (id.kind() == IdentifierKind.MethodIdentifier)
1203
		{
1204
			doError(aname, "Method access in do-od block not allowed.");
1205
			return;
1206
			// access via self
1207
			/*
1208
            Identifier self = pState.Lookup("self");
1209
            if (self == null)
1210
                doError(aname, "Self access of method: Can not find 'self' symbol! (internal error)");
1211
            IdentifierExpression aself = new IdentifierExpression(self, aname.getLine(), aname.getCharPositionInLine());
1212
            aself.setIsSelf(true);
1213
            callexpr = new CallExpression(
1214
                new AccessExpression(aself,
1215
                    new IdentifierExpression(id, aname.getLine(), aname.getCharPositionInLine()), aname.getLine(), aname.getCharPositionInLine()),
1216
                    m_params, aname.getLine(), aname.getCharPositionInLine(), GetScope());
1217
			 */
1218
		}
1219
		else
1220
			callexpr = new CallExpression(
1221
					new IdentifierExpression(id, aname.getLine(), aname.getCharPositionInLine()),
1222
					m_params, aname.getLine(), aname.getCharPositionInLine(), GetScope());
1223

  
1224
		if (amapexpression != null)
1225
		{
1226
			ExpressionKind akind = ExpressionKind.foldLR;
1227
			if (maptoken.getType() == ooaLexer.T_FOLDLR)
1228
				akind = ExpressionKind.foldLR;
1229
			else if (maptoken.getType() == ooaLexer.T_FOLDRL)
1230
				akind = ExpressionKind.foldRL;
1231
			else
1232
				assert(false);
1233

  
1234
			callexpr = new TernaryOperator(akind, callexpr, null, amapexpression,
1235
					currentLine(), currentPos(), GetScope());
1236
		}
1237
		final Call statement = new Call(callexpr, currentLine(), currentPos());
1238
		top.AddStatement(statement);
1239
	}
1240

  
1241
	/*adds skip statement instead of call to do-od block*/
1242
	 void addSkipStatementToBlockList(Block top)
1243
	{
1244
		top.AddStatement(new SkipStatement(currentLine(), currentPos()));
1245
	}
1246

  
1247

  
1248
	/* add anonymous action to do-od block */
1249
	 void addToBlockList(Block top, Statement gcmd)
1250
	{
1251
		if (gcmd != null)
1252
			top.AddStatement(gcmd);
1253
	}
1254

  
1255
	/* add the do-od block to the action system type */
1256
	 void addActionBlock(OoActionSystemType aTypeSymbol, Block bl)
1257
	{
1258
		aTypeSymbol.SetDoOdBlock(bl);
1259
	}
1260

  
1261
	/* push block */
1262
	 void pushBlockToResolveStack(IScope toPush)
1263
	{
1264
		pState.PushResolveStack(toPush);
1265
	}
1266

  
1267
	/* pop block */
1268
	 void popBlockFromResolveStack(IScope toPop)
1269
	{
1270
		if (toPop != null)
1271
		{
1272
			assert(pState.currentScope == toPop); // ref eq.
1273
			pState.PopResolveStack();
1274
		}
1275
	}
1276

  
1277
	/* add block var */
1278
	 void addBlockVariable(Block seqList, Token varname, UlyssesType aType)
1279
	{
1280
		if (aType == null)
1281
		{
1282
			doError(varname, String.format("%s lacks type!", varname.getText()));
1283
		}
1284
		try
1285
		{
1286
			seqList.AddIdentifier(new LocalVariableIdentifier(varname, aType, GetScope()));
1287
		}
1288
		catch (final ArgumentException e)
1289
		{
1290
			doError(varname, String.format("%s redefined!", varname.getText()));
1291
		}
1292
	}
1293

  
1294

  
1295
	 QualitativeConstraintStatement createTwoVarConstraintStatement(Token id1, Token id2, QualitativeConstraintOperation op)
1296
	{
1297
		Identifier var1 = pState.Lookup(id1);
1298
		if (var1 == null)
1299
		{
1300
			var1 = new ExpressionVariableIdentifier(id1.getText(), id1.getLine(), id1.getCharPositionInLine());
1301
			var1.SetType(new AnyType((ExpressionVariableIdentifier)var1));
1302

  
1303
			GetScope().AddIdentifier(var1, null);
1304

  
1305
			doWarning(id1, String.format("Free variable in qualitative constraint: '%s'.", id1.getText()));
1306
		}
1307

  
1308
		Identifier var2 = pState.Lookup(id2);
1309
		if (var2 == null)
1310
		{
1311
			var2 = new ExpressionVariableIdentifier(id2.getText(), id2.getLine(), id2.getCharPositionInLine());
1312
			var2.SetType(new AnyType((ExpressionVariableIdentifier)var2));
1313

  
1314
			GetScope().AddIdentifier(var2, null);
1315

  
1316
			doWarning(id1, String.format("Free variable in qualitative constraint: '%s'.", id2.getText()));
1317
		}
1318

  
1319
		final QualitativeConstraintStatement result = new QualitativeConstraintStatement(var1, var2, op, id1.getLine(), id1.getCharPositionInLine());
1320
		return result;
1321
	}
1322

  
1323

  
1324
	 QualitativeConstraintStatement createQualEqualConstraintStatement(Token id1, Token id2)
1325
	{
1326
		return createTwoVarConstraintStatement(id1, id2, QualitativeConstraintOperation.Equal);
1327
	}
1328

  
1329
	 QualitativeConstraintStatement createQualArithConstraintStatement(Token id1, Token id2, Token id3, Token op)
1330
	{
1331
		Identifier var1 = pState.Lookup(id1);
1332
		if (var1 == null)
1333
		{
1334
			var1 = new ExpressionVariableIdentifier(id1.getText(), id1.getLine(), id1.getCharPositionInLine());
1335
			var1.SetType(new AnyType((ExpressionVariableIdentifier)var1));
1336

  
1337
			GetScope().AddIdentifier(var1, null);
1338

  
1339
			doWarning(id1, String.format("Free variable in qualitative constraint: '%s'.", id1.getText()));
1340
		}
1341

  
1342
		Identifier var2 = pState.Lookup(id2);
1343
		if (var2 == null)
1344
		{
1345
			var2 = new ExpressionVariableIdentifier(id2.getText(), id2.getLine(), id2.getCharPositionInLine());
1346
			var2.SetType(new AnyType((ExpressionVariableIdentifier)var2));
1347

  
1348
			GetScope().AddIdentifier(var2, null);
1349

  
1350
			doWarning(id1, String.format("Free variable in qualitative constraint: '%s'.", id2.getText()));
1351
		}
1352

  
1353
		Identifier var3 = pState.Lookup(id3);
1354
		if (var3 == null)
1355
		{
1356
			var3 = new ExpressionVariableIdentifier(id3.getText(), id3.getLine(), id3.getCharPositionInLine());
1357
			var3.SetType(new AnyType((ExpressionVariableIdentifier)var3));
1358

  
1359
			GetScope().AddIdentifier(var3, null);
1360

  
1361
			doWarning(id1, String.format("Free variable in qualitative constraint: '%s'.", id3.getText()));
1362
		}
1363
		QualitativeConstraintOperation operation;
1364
		switch (op.getType())
1365
		{
1366
		case ooaParser.T_SUM:
1367
			operation = QualitativeConstraintOperation.Sum;
1368
			break;
1369
		case ooaParser.T_DIFF:
1370
			operation = QualitativeConstraintOperation.Diff;
1371
			break;
1372
		case ooaParser.T_PROD:
1373
			operation = QualitativeConstraintOperation.Prod;
1374
			break;
1375
		default:
1376
			doError(op, String.format("'%s' unknown operation", op.getText()));
1377
			return null;
1378
		}
1379

  
1380
		final QualitativeConstraintStatement result = new QualitativeConstraintStatement(var1, var2, var3, operation, id1.getLine(), id1.getCharPositionInLine());
1381
		return result;
1382
	}
1383

  
1384
	 QualitativeConstraintStatement createQualDerivConstraintStatement(Token id1, Token derivid)
1385
	{
1386
		return createTwoVarConstraintStatement(id1, derivid, QualitativeConstraintOperation.Deriv);
1387
	}
1388

  
1389

  
1390

  
1391
	/* creates a general binary operator without any children */
1392
	 BinaryOperator createBinaryOperator(ExpressionKind akind)
1393
	{
1394
		final Token token = input.LT(-1);
1395
		return new BinaryOperator(akind, null, null, token.getLine(), token.getCharPositionInLine());
1396
	}
1397

  
1398

  
1399
	/* creates a general unary operator without child */
1400
	 UnaryOperator createUnaryOperator(ExpressionKind unaryOperatorType)
1401
	{
1402
		final Token token = input.LT(-1);
1403
		return new UnaryOperator(unaryOperatorType, null, token.getLine(), token.getCharPositionInLine());
1404
	}
1405

  
1406
	/* create a conditional expression */
1407
	 Expression createConditionalExpression(Expression ce, Expression te, Expression ee, Token ef)
1408
	{
1409
		return new TernaryOperator(ExpressionKind.conditional, ce, te, ee, ef.getLine(), ef.getCharPositionInLine(), GetScope());
1410
	}
1411

  
1412
	/* create a quantifier expression */
1413
	 Quantifier createQuantifierExpression(Token t)
1414
	{
1415
		Quantifier result = null;
1416
		if (t.getType() == ooaLexer.T_FORALL)
1417
			result = new ForallQuantifier(null, t.getLine(), t.getCharPositionInLine());
1418
		else
1419
			result = new ExistsQuantifier(null, t.getLine(), t.getCharPositionInLine());
1420

  
1421

  
1422
		pState.PushResolveStack(result);
1423
		return result;
1424
	}
1425

  
1426
	/* add a bound variable to the quantifier */
1427
	 void addBoundVarToQuantifierExpression(Quantifier result, Token id, UlyssesType id_type)
1428
	{
1429
		/*note: this might be a bit harsh, but for now it's easier to demand uniquely named vars,
1430
                without any hiding. Could be fixed in searching only the first resolve level for
1431
                dupes..
1432
		 */
1433
		final Identifier sym = pState.Lookup(id);
1434
		if (sym != null)
1435
			doError(id, String.format("'%s' already defined!", id.getText()));
1436
		else
1437
		{
1438
			if (id_type == null)
1439
				doError(id, String.format("%s lacks type (null).", id.getText()));
1440
			final Identifier newvar = new ExpressionVariableIdentifier(id, id_type, GetScope());
1441
			result.AddIdentifier(newvar, null);
1442
		}
1443
	}
1444

  
1445
	/* add the expression to the quantifier */
1446
	 void addExpressionToQuantifier(Quantifier result, Expression e)
1447
	{
1448
		result.SetChild(e);
1449
	}
1450

  
1451
	/* remove local variables from resolve stack */
1452
	 void removeBoundVarsFromResolveStack(Quantifier result)
1453
	{
1454
		if (result != null)
1455
			pState.PopResolveStack();
1456
	}
1457

  
1458

  
1459
	/* create a boolean constant */
1460
	 LeafExpression createBoolConstant(boolean p)
1461
	{
1462
		final Token token = input.LT(-1);
1463
		return new ValueExpression<Boolean>(p, token.getLine(), token.getCharPositionInLine(), Boolean.class);
1464
	}
1465

  
1466
	/* create a nil */
1467
	 LeafExpression createNullPointerConstant()
1468
	{
1469
		final Token token = input.LT(-1);
1470
		return new ValueExpression<Object>(null, token.getLine(), token.getCharPositionInLine(), Object.class);
1471
	}
1472

  
1473
	/* create a 'self' identifier */
1474
	 LeafExpression createSelfPointer()
1475
	{
1476
		final Token token = input.LT(-1);
1477
		final Identifier self = pState.Lookup("self");
1478
		if (self == null)
1479
		{
1480
			doError(token, "Could not resolve 'self'");
1481
			return new UnresolvedIdentifierExpression(token, GetScope());
1482
		}
1483

  
1484
		final IdentifierExpression result = new IdentifierExpression(self, token.getLine(), token.getCharPositionInLine());
1485
		result.setIsSelf(true);
1486

  
1487
		return result;
1488
	}
1489

  
1490
	/* create a float const */
1491
	 LeafExpression createFloatConstant(Token t_fl)
1492
	{
1493
		return new ValueExpression<Double>(Double.parseDouble(t_fl.getText()), t_fl.getLine(), t_fl.getCharPositionInLine(), Double.class);
1494
	}
1495

  
1496
	/* create int const */
1497
	 LeafExpression createIntConstant(Token t_in)
1498
	{
1499
		return new ValueExpression<Integer>(Integer.parseInt(t_in.getText()), t_in.getLine(), t_in.getCharPositionInLine(), Integer.class);
1500
	}
1501

  
1502
	/* set children of binary operator*/
1503
	 Expression addBinaryExpression(BinaryOperator binexpr, Expression expr, Expression e2)
1504
	{
1505
		binexpr.SetLeftChild(expr);
1506
		binexpr.SetRightChild(e2);
1507
		return binexpr;
1508
	}
1509

  
1510
	/* set child of unary expr */
1511
	 Expression addUnaryExpression(UnaryOperator unexpr, Expression e)
1512
	{
1513
		if (unexpr != null)
1514
		{
1515
			unexpr.SetChild(e);
1516
			return unexpr;
1517
		}
1518
		else
1519
			return e;
1520
	}
1521

  
1522

  
1523

  
1524
	/* create a list */
1525
	 ListConstructor createInitializedList()
1526
	{
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff