Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / parser / ooa.g @ 9

1
/*  
2
			ANTLR Grammar for OO-Action Systems
3
			 (C) Willibald Krenn, 2009 - 2015
4

    
5

    
6
  Notes
7
  ~~~~~
8
  	(*) No recursion
9
  	(*) float acutally is fixed-point!
10
	(*) Named actions can only be "called" within the do-od block 
11
	(*) Methods can be called from within an action and a method.
12
	    Attention: Mutual Recursion not supported!
13

    
14
  FixMe
15
  ~~~~~
16
  	(*) List-Enum: Length Restriction! (Defaults to 500 for now)
17
	(*) subseteq missing
18
	
19

    
20
			 
21
  History
22
  ~~~~~~~
23
  Changes 1.07 to 1.08
24
    ~ remove support for Qualitative Action Systems
25

    
26
  Changes 1.06 to 1.07
27
    ~ move to org.momut naming
28
  
29
  Changes 1.05 to 1.06
30
  	~ make action blocks more capable, add the projection feature already available in the do-od block.
31
	- disable support for continuous actions
32
  
33
  Changes 1.04 to 1.05
34
  	~ Fix bug with set constuctor: set with only one element produced wrong AST (inner element wasn't added correctly).
35
  
36
  Changes 1.03 to 1.04
37
        ~ Move to JAVA
38
  
39
  Changes 1.02 to 1.03
40
  	+ option to name objects when they are constructed: new (<class>,"<name>")
41
  
42
  Changes 1.00 to 1.02
43
  	+ cast operator for objects ( ... as <typename> )
44

    
45
  Changes 1.00 to 1.01
46
  	+ enum-type with fixed integer values
47
  
48
  Changes 0.99b to 1.00
49
  	+ constant section added (consts a=4; b=4)
50
  	+ limits of simple types and lists can be const
51
  	+ local vars allowed in methods (... = var... begin...end)
52
  	+ prioritized composition on statement level
53
  	+ skip in do-od block
54
  	+ filter expression in do-od block sequential var statement
55
  	+ fold operator
56
  	
57
  Changes 0.99 to 0.99b
58
        - disabled sequential composition of action systems (remains in grammar, though out-commented)
59
        
60
  Changes 0.98 to 0.99
61
        ~ changed QR syntax.
62
  
63
  Changes 0.97 to 0.98
64
  	~ changed syntax for list and set comprehension
65
  	  list comprehension:
66
  	  '[' expression '|' 'var' id ':' type (';' id ':' type)* ('&' expression)? ']'
67
  	  set comprehension
68
  	  '{' expression '|' 'var' id ':' type (';' id ':' type)* ('&' expression)? '}'
69
  	  
70
  	  Usage: defined variables will sweep over value-range. If the latter expression
71
  	  (after '&') evaluates to true (hence this expression must return a bool) with
72
  	  the current valuation of the defined vars, the values are used to evaluate the
73
  	  first expression, which has to return a value of the correct type.
74
  	  
75
  	  Example:
76
  	  type
77
  	    myint = int [0..300000];
78
  	    mytuple = (myint, myint)
79
  	  var
80
  	     l_tuple : list of mytuple = [nil];
81
  	     l_int : list of myint = [nil];
82
  	    ...
83
  	      l_int := [l_tuple[x][0] | var x: myint & x < len l_tuple ]
84
  	  
85
  	  
86
  	+ list element access by '[int]' allowed!
87

    
88

    
89
  Changes 0.96 to 0.97
90
  	+ tuple-type initialization now properly supported
91
  	+ binary operator precedence handling
92
  	+ local variables in named actions
93
  	+ support for (<expression>).<reference> and
94
  	              (<expression>).<accessExpression>
95
  	~ conditional expression: End required.
96
  	- remove support for power-operator 
97
  	  (may be we need to do calculation backwards)
98

    
99
  Changes 0.95 to 0.96
100
  	~ string literals now ".."
101
  	~ priming of identifier access only supported at the end of the
102
  	  expression
103

    
104
  Changes 0.9 to 0.95
105
  	+ composition of action systems in 'system' block
106
  	~ Produce C# code
107
  	~ Operator Precedence
108
  	~ vars in action composition
109
  	~ forall/extists now with colon instead of in
110

    
111

    
112
  Earlier changes  removed.
113
			 
114
*/
115

    
116

    
117
grammar ooa;
118

    
119
options {	
120
  k = 2;
121
  superClass = ooaCustomParser;
122
}
123

    
124

    
125
@lexer::header
126
{
127
/*
128
    Ulysses OO-Action System Parser
129
    
130
    Copyright Graz University of Technology 2009
131
    Copyright AIT Austrian Institute of Technology 2013
132
 */
133
 package org.momut.ooas.parser;
134
}
135

    
136

    
137
@parser::header
138
{
139
 /*
140
    Ulysses OO-Action System Parser
141

    
142
    Copyright Graz University of Technology 2009
143
    Copyright AIT Austrian Institute of Technology 2013
144
 */
145
 package org.momut.ooas.parser;
146

    
147
 import org.momut.ooas.ast.expressions.*;
148
 import org.momut.ooas.ast.statements.*;
149
 import org.momut.ooas.ast.identifiers.*;
150
 import org.momut.ooas.ast.types.*;
151
 import org.momut.ooas.ast.types.FunctionType.FunctionTypeEnum;
152
}
153

    
154
ooActionSystems 
155
	:	{initializeTopLevelParserState();}
156

    
157
	         (T_CONSTS namedConstList)?
158
		
159
		 T_TYPES 
160
		  	namedTypeList
161
		 T_SYSTEM
162
			comp=asTypeComposition[null]
163
			{fixUpRun(comp);}
164
	;
165

    
166

    
167

    
168
//
169
//  ------------   named consts  ------------ 
170
//
171

    
172
namedConstList
173
	:	namedConst (T_SEMICOLON namedConst)*
174
	;
175
	
176
namedConst
177
	:	aName=T_IDENTIFIER
178
		T_EQUAL
179
		anExpr=expression
180
		{addNamedConst(aName,anExpr);}
181
	;
182

    
183

    
184
//
185
//  ------------   named types  ------------ 
186
//
187
namedTypeList 
188
	:	namedType (T_SEMICOLON namedType)*
189
	;
190

    
191
namedType 
192
	:	aName=T_IDENTIFIER 
193
		T_EQUAL 
194
		(
195
			aType=complexType 	 {createNamedType(aName,aType);}
196
		|	anOoaType=ooActionSystem {createNamedType(aName,anOoaType);}
197
		)		
198
		
199
	;
200

    
201

    
202
asTypeComposition [IdentifierList top]
203
	returns [IdentifierList prioList]
204
	:  	{prioList = new PrioIdentifierList(top);}
205
		asTypeCompositionParallel[prioList]  (T_PRIO asTypeCompositionParallel[prioList] )*
206
	;
207

    
208
asTypeCompositionParallel [IdentifierList top]
209
	:  	{IdentifierList parList = new NondetIdentifierList(top);}
210
		asTypeCompositionSequential[parList] (T_NONDET asTypeCompositionSequential[parList])*
211
	;
212

    
213
asTypeCompositionSequential [IdentifierList top]
214
	:  	{IdentifierList seqList = new SeqIdentifierList(top);}
215
		asTypeCompositionBlockParen[seqList] //(T_SEMICOLON asTypeCompositionBlockParen[seqList])*
216
	;
217

    
218
asTypeCompositionBlockParen [IdentifierList top]
219
	: T_LPAREN asTypeComposition[top] T_RPAREN
220
	| aName=T_IDENTIFIER {addToIdentifierList(top,aName);}
221
	;
222
	
223

    
224
//
225
//  ------------   basic types    ------------ 
226
//
227

    
228
complexType 
229
	returns [Type aTypeSymbol]
230
	@init{ 
231
		aTypeSymbol = null;
232
	}	
233
	:	T_LIST  T_LSQPAREN numOfElements=(T_INTNUMBER|T_IDENTIFIER) T_RSQPAREN T_OF  innertype=complexType 
234
			{aTypeSymbol = createListType(numOfElements,innertype);}
235

    
236
		// list type with predefined elements (dupes of each element as many as needed) FIXME: Length Restriction!
237
	|	T_LSQPAREN alistelem=T_IDENTIFIER {aTypeSymbol = createListEnumType(alistelem);} 
238
			(T_COMMA otherlistelem=T_IDENTIFIER {addToListEnumType(aTypeSymbol,otherlistelem);})* T_RSQPAREN // set of identifiers..
239

    
240
		// maps do not really need a length restriction, as simpleType already is restricted..
241
	|	T_MAP   (T_LSQPAREN numOfElements=(T_INTNUMBER|T_IDENTIFIER) T_RSQPAREN)? mapfromtype=simpleType T_TO maptotype=complexType 
242
			{aTypeSymbol = createMapType(numOfElements,mapfromtype,maptotype);}
243
		// tuple
244
	|	 T_LPAREN aType=complexType {aTypeSymbol = createTupleType(aType);} 
245
			(T_COMMA anotherType=complexType {addToTupleType(aTypeSymbol,anotherType);})*  T_RPAREN
246
		
247
		// some simple type (note that this includes identifiers, which may be complex object types..)	
248
	|	r=simpleType {aTypeSymbol = r;}
249
	;
250
	finally
251
		{fixupComplexType(aTypeSymbol);}
252

    
253
	
254
simpleType 
255
	returns [Type aTypeSymbol]
256
	@init{ 
257
		aTypeSymbol = null;
258
	}
259
	:	T_BOOL  {aTypeSymbol = createBoolType();}
260
	
261
		// ints plus subtypes
262
	|	T_INT T_LSQPAREN rangeLow=(T_INTNUMBER|T_INFTY|T_IDENTIFIER) T_RANGETO rangeHigh=(T_INTNUMBER|T_INFTY|T_IDENTIFIER) T_RSQPAREN  
263
			{aTypeSymbol = createIntType(rangeLow,rangeHigh);}
264
			
265
		// floats plus subtypes
266
	|	T_FLOAT  T_LSQPAREN rangeLow=(T_FLOATNUMBER|T_INFTY|T_IDENTIFIER) T_RANGETO rangeHigh=(T_FLOATNUMBER|T_INFTY|T_IDENTIFIER) T_RSQPAREN 
267
			{aTypeSymbol = createFloatType(rangeLow,rangeHigh);}
268
			
269
		// char
270
	|	T_CHAR {aTypeSymbol = createCharType();}
271
		
272
		// simple type, domain restricted to the values within the given set. (operators supported: equal, not equal) - may be casted to integer if
273
		// explicit int values are given
274
	|	T_CBRL aRangeValue=T_IDENTIFIER (T_EQUAL optVal=T_INTNUMBER)? {aTypeSymbol = createEnumType(aRangeValue, optVal);} 
275
			(T_COMMA otherRangeValue=T_IDENTIFIER (T_EQUAL otherOptVal=T_INTNUMBER)? {addToEnumType(aTypeSymbol,otherRangeValue,otherOptVal); otherOptVal=null;})* T_CBRR
276
			
277
	|	aType=T_IDENTIFIER {aTypeSymbol = getNamedType(aType);} // alias could be simple type - otherwise, it's a complex type!!
278
	;
279
	finally
280
		{fixupSimpleType(aTypeSymbol);}
281

    
282

    
283

    
284

    
285

    
286

    
287
ooActionSystem 
288
	returns [OoActionSystemType aTypeSymbol]
289
	@init{ 
290
		boolean autoCons = false; 
291
		aTypeSymbol = null;
292
		refinesSystemName = null;
293
	}
294
	:      (T_AUTOCONS {autoCons = true;})? 
295
		T_SYSTEM (T_LPAREN refinesSystemName=T_IDENTIFIER T_RPAREN)?		 
296
		{aTypeSymbol = createOoaType(refinesSystemName,autoCons);}
297
		'|['
298
			(T_VAR attrList)?
299
			(T_METHODS methodList)?
300
			(T_ACTIONS namedActionList)?
301
			(T_DO (bl=actionBlock[null] {addActionBlock(aTypeSymbol,bl);})? T_OD)?
302
		']|'
303
	;
304
	finally
305
		{fixupOoaType(aTypeSymbol);}
306
	
307

    
308

    
309
	
310
//
311
//  ------------   variables (objects and simple types)    ------------ 
312
//
313
attrList
314
	:	{BeginParsingAttributes();}
315
	 	attr (T_SEMICOLON attr)*
316
	;
317
	finally {
318
		EndParsingAttributes();
319
	}
320

    
321
attr
322
	@init{ 
323
		boolean isStatic = false; 
324
		boolean isCtr = false;
325
		boolean isObs = false;				
326
		
327
	}
328
	: 	(T_STATIC {isStatic = true;})? (T_OBS {isObs = true;} | T_CTRL {isCtr = true;})? 
329
		varname=T_IDENTIFIER  T_COLON aType=complexType (T_EQUAL anExpr=expression)?
330
		{createAttribute(varname, isStatic, isObs, isCtr, aType, anExpr);}
331
	;
332

    
333
//
334
//  ------------   methods    ------------ 
335
//	
336
methodList 
337
	: 	method (T_SEMICOLON method)*
338
	;
339

    
340
method	
341
	@init {	
342
		FunctionIdentifier newMethod = null;
343
	}
344
	:	mname=T_IDENTIFIER  {newMethod = createMethodSymbol(mname);}
345
		(T_LPAREN methodParameterList[newMethod]  T_RPAREN)? 
346
		(T_COLON rt=complexType {setMethodReturnType(newMethod,rt);})?	// actions can not have a return type!!					
347
		 T_EQUAL 
348
		 ( T_VAR localActionVars[newMethod] 'begin')?                                   // var here always means vars of the method. This disables the var of the actionBody!
349
		                                                                                                                 // If that is wanted, the user needs to use parens... Alternatively we could force the "begin" which feels cumbersome.
350
		                                                                                                                 // Using a semantic predicate here triggers a bug in the codegen it seems..
351
		statements=actionBody[null] {addMethodBody(newMethod,statements);} 
352
		T_END		
353
	;
354
	finally
355
		{popResolveStack(newMethod);}
356

    
357
methodParameterList[FunctionIdentifier newMethod]
358
	:	 paramName=T_IDENTIFIER T_COLON atype=complexType {addMethodParameter(newMethod,paramName,atype);}
359
			(T_COMMA otherparam=T_IDENTIFIER T_COLON othertype=complexType
360
			{addMethodParameter(newMethod,otherparam,othertype);} )*		
361
	;
362

    
363

    
364
//
365
//  ------------   named, anonymous actions    ------------ 
366
//	
367

    
368
namedActionList 
369
	:	namedAction (T_SEMICOLON namedAction)*
370
	;
371

    
372
namedAction 
373
	@init {
374
		FunctionTypeEnum actionType;
375
		FunctionIdentifier newAction = null;
376
	}
377
	:	{actionType = FunctionTypeEnum.Internal;}
378
		(T_CTRL {actionType = FunctionTypeEnum.Controllable;}| T_OBS {actionType = FunctionTypeEnum.Observable;}| )
379
		 actionname=T_IDENTIFIER  {newAction = createNamedAction(actionname,actionType);}
380
		(T_LPAREN methodParameterList[newAction]  T_RPAREN)? 
381
		T_EQUAL	
382
		(T_VAR localActionVars[newAction] )? 
383
		body=discreteActionBody  
384
		{addActionBody(newAction,body);}
385
	;	
386
	finally
387
		{popResolveStack(newAction);}
388

    
389

    
390
localActionVars[FunctionIdentifier newMethod]
391
	:	// a named, discrete action may have local variables.
392
		id1=T_IDENTIFIER T_COLON t1=complexType  {addLocalVariableToNamedAction(newMethod,id1,t1);}
393
		 (T_SEMICOLON id2=T_IDENTIFIER T_COLON t2=complexType
394
		 {addLocalVariableToNamedAction(newMethod,id2,t2);} )*
395
	;	
396

    
397

    
398

    
399
anonymousAction 
400
	returns [GuardedCommand result]
401
	:	
402
		b=discreteActionBody {result = b;}
403
	;
404

    
405
discreteActionBody 
406
	returns [GuardedCommand result]
407
	@init{
408
		result = null;
409
	}
410
	:
411
		{result = createGuardedCommandStatement(); pushBlockToResolveStack(result);}	
412
		T_REQUIRES expr=expression T_COLON
413
			bdy=actionBody[null]
414
		T_END
415
		{addExprAndBlockToGuardedCommand(result,expr,bdy);}
416
	;
417
	finally
418
		{popBlockFromResolveStack(result);}
419
	
420
	
421
//
422
//  ------------   do-od block    ------------ 
423
//	
424

    
425
actionBlock [Block top]
426
	returns [Block prioList]
427
	:  	{prioList = createPrioBlock(top);  pushBlockToResolveStack(prioList);}
428
		 actionBlockParallel[prioList] (T_PRIO actionBlockParallel[prioList])* 
429
	;	
430
	finally
431
		{popBlockFromResolveStack(prioList);}
432
	
433
actionBlockParallel [Block top]
434
	@init 	{	Block parList = createNondetBlock(top); 
435
		 	pushBlockToResolveStack(parList);
436
		}
437
	:	actionBlockSequential[parList] (T_NONDET actionBlockSequential[parList])*
438
	;	
439
	finally
440
		{popBlockFromResolveStack(parList);}
441
// atomic sequential composition of actions	
442
actionBlockSequential [Block top]
443
	@init  	{
444
			Block seqList = createSeqBlock(top);
445
			pushBlockToResolveStack(seqList);
446
		}
447
	:	 (T_VAR syms=blockvarlist[seqList] ('&' sexpr=expression {addSeqBlockExpression(seqList,sexpr);} )? T_COLON )? 
448
		 actionBlockParen[seqList] (T_SEMICOLON actionBlockParen[seqList])*
449
	;	
450
	finally
451
		{popBlockFromResolveStack(seqList);}
452

    
453
actionBlockParen [Block top]
454
	:	T_LPAREN actionBlock[top] T_RPAREN
455
	|	anonymousOrNamedAction[top]
456
	;	
457

    
458
anonymousOrNamedAction [Block top]
459
	:	gcmd=anonymousAction {addToBlockList(top,gcmd);}
460
	|	aname=T_IDENTIFIER 
461
	         (T_LPAREN  m_params=methodCallParams T_RPAREN)? 
462
	         (amap=(T_FOLDLR|T_FOLDRL) '(' amapexpr=expression ')')?
463
		{addNamedActionCallToBlockList(top,aname,m_params,amap,amapexpr);}
464
	|	T_SKIP	{addSkipStatementToBlockList(top);}
465
	;
466

    
467

    
468
blockvarlist [Block seqList]
469
	:	blockvar[seqList]  (T_SEMICOLON blockvar[seqList] )*
470
	;
471

    
472
blockvar [Block seqList]
473
	: 	varname=T_IDENTIFIER  T_COLON aType=complexType 
474
		{addBlockVariable(seqList,varname,aType);}
475
	;
476

    
477
		
478

    
479
//
480
//  ------------  action body  of non-continuous actions ------------ 
481
//
482
	
483
actionBody[Block top]
484
	returns [Block result]
485
	:	{result = createPrioBlock(top); pushBlockToResolveStack(result);}
486
		actionBodyParallel[result] (T_PRIO actionBodyParallel[result])? 
487
	;  
488
	finally
489
		{popBlockFromResolveStack(result);}
490
	
491
actionBodyParallel[Block top]
492
	returns [Block result]
493
	:	{result = createNondetBlock(top); pushBlockToResolveStack(result);}
494
		actionBodySequential[result]
495
		(T_NONDET olst=actionBodySequential[result])*
496
	;	
497
	finally
498
		{popBlockFromResolveStack(result);}
499

    
500
	
501
// seq binds stronger than nondet, i.e. a;b;cd;e is read as (a;b;c)[](d;e)	
502
actionBodySequential[Block top]
503
	returns [SeqBlock result]
504
	:	{result = createSeqBlock(top); pushBlockToResolveStack(result);}
505
		(T_VAR syms=blockvarlist[result] ('&' sexpr=expression {addSeqBlockExpression(result,sexpr);} )? T_COLON )?
506
		 actionBodyParen[result] (T_SEMICOLON actionBodyParen[result])*
507
	;	
508
	finally
509
		{popBlockFromResolveStack(result);}
510
	
511
	
512
actionBodyParen [SeqBlock top]
513
	:	 T_LPAREN actionBody[top]  T_RPAREN
514
	|	stmt=statement
515
		{addToStatementList(top,stmt);}
516
	;	
517

    
518

    
519
statement
520
	returns [Statement result]
521
	@init {
522
		boolean popFromResolveStack = false;
523
		result = null;
524
	}
525
	:	T_ABORT {result = createAbortStatement();}
526
	|	T_SKIP	{result = createSkipStatement();}
527
	|	T_BREAK {result = createBreakStatement();}
528
	|	T_KILL T_LPAREN aname=(T_IDENTIFIER | T_SELF) T_RPAREN	{result = createKillStatement(aname);}
529
	| 	gc=discreteActionBody {result = gc;}
530
	|	aqname=reference 
531
			   ( 	    // single assignment			   	    
532
			   	    T_ASSIGNMENT  aexp=expression  {result = createSingleAssignmentStatement(aqname,aexp);}
533
			           (T_WITH ndexp=expression {addConstraintToAssignment(result,ndexp);})? // nondet assignment
534
			           
535
			           // multi assignment
536
				|  {result = createMultipleAssignmentStatementLHS(aqname);}
537
				  (T_COMMA malhs=reference  {addMultipleAssignmentStatementLHS(result,malhs);})+ 
538
				   T_ASSIGNMENT 
539
				   {pushAssignmentOnResolveStack(result); popFromResolveStack = true;} 
540
				   mexp=expression
541
				   {addMutlipleAssignmentStatementRHS(result,mexp);}
542
				   (T_COMMA mexp2=expression {addMutlipleAssignmentStatementRHS(result,mexp2);})+
543
				   (T_WITH ndex2=expression {addConstraintToAssignment(result,ndex2);})? // nondet assignment
544
				   
545
				   // just a call of a method.
546
				| {result = createCallStatement(aqname);}
547
		     	    )
548
	;	
549
	finally {
550
	       if (popFromResolveStack == true)
551
	            popAssignmentOffResolveStack(result);
552
	}
553

    
554
//
555
//  ------------   expression    ------------ 
556
//
557
expression
558
	returns [Expression expr]
559
	@init{
560
		ArrayList<BinaryOperator> operators = new ArrayList<BinaryOperator>();
561
		ArrayList<Expression> expressions = new ArrayList<Expression>();		
562
	}
563
	:	left=atomExpression	
564
		{expressions.add(left);}
565
		( op=binoperator
566
		  right=atomExpression
567
		  {
568
		  	if (op != null) {
569
		  		operators.add(op);
570
		  		expressions.add(right);
571
		  	}
572
		  }
573
		)*
574
		{expr = createPrecedenceTree(expressions,operators);}
575
	;
576

    
577

    
578
binoperator	
579
	returns [BinaryOperator binop]
580
	:	T_BIIMPLIES
581
		{binop = createBinaryOperator(ExpressionKind.biimplies);}
582
	|	T_GREATER	
583
		{binop = createBinaryOperator(ExpressionKind.greater);}
584
	|	T_GREATEREQUAL
585
		{binop = createBinaryOperator(ExpressionKind.greaterequal);}
586
	|	T_LESS	
587
		{binop = createBinaryOperator(ExpressionKind.less);}
588
	|	T_LESSEQUAL
589
		{binop = createBinaryOperator(ExpressionKind.lessequal);}
590
	|	T_EQUAL			// bool, numeric, char, lists, maps
591
		{binop = createBinaryOperator(ExpressionKind.equal);}
592
	|	T_NOTEQUAL		// bool, numeric, char, lists, maps
593
		{binop = createBinaryOperator(ExpressionKind.notequal);}
594
	|	T_IMPLIES
595
		{binop = createBinaryOperator(ExpressionKind.implies);}
596
	|	T_MINUS	
597
		{binop = createBinaryOperator(ExpressionKind.minus);}
598
	|	T_SUM	
599
		{binop = createBinaryOperator(ExpressionKind.sum);}
600
	|	T_IN T_SET?	// A * list of A -> bool
601
		{binop = createBinaryOperator(ExpressionKind.elemin);}
602
	|	T_NOT T_IN T_SET?	// A * list of A -> bool
603
		{binop = createBinaryOperator(ExpressionKind.notelemin);}
604
	|	T_SUBSET	// list of A * list of A -> bool (does not respect dupes)
605
		{binop = createBinaryOperator(ExpressionKind.subset);}
606
	|	T_OR
607
		{binop = createBinaryOperator(ExpressionKind.or);}
608
	|	T_DIV
609
		{binop = createBinaryOperator(ExpressionKind.div);}
610
	|	T_PROD	
611
		{binop = createBinaryOperator(ExpressionKind.prod);}
612
	|	T_IDIV	
613
		{binop = createBinaryOperator(ExpressionKind.idiv);}
614
	|	T_MOD	
615
		{binop = createBinaryOperator(ExpressionKind.mod);}
616
	|	T_UNION		// list of A * list of A -> list of A (does not respect dupes)
617
		{binop = createBinaryOperator(ExpressionKind.union);}
618
	|	T_DIFF		// list of A * list of A -> list of A (does not respect dupes)
619
		{binop = createBinaryOperator(ExpressionKind.diff);}
620
	|	T_INTER		// list of A * list of A -> list of A (does not respect dupes)
621
		{binop = createBinaryOperator(ExpressionKind.inter);}
622
	|	T_AND  
623
		{binop = createBinaryOperator(ExpressionKind.and);}				
624
	|	T_POW  
625
		{binop = createBinaryOperator(ExpressionKind.pow);}				
626
	|	T_CONC	// list of A * list of A -> list of A
627
		{binop = createBinaryOperator(ExpressionKind.conc);}			
628
	|	T_DOMRESBY	// list of A * map A to B -> map A to B
629
		{binop = createBinaryOperator(ExpressionKind.domresby);}
630
	|	T_DOMRESTO	// list of A * map A to B -> map A to B
631
		{binop = createBinaryOperator(ExpressionKind.domresto);}
632
	|	T_RNGRESBY	// map A to B * list of B -> map A to B
633
		{binop = createBinaryOperator(ExpressionKind.rngresby);}
634
	|	T_RNGRESTO	// map A to B * list of B -> map A to B
635
		{binop = createBinaryOperator(ExpressionKind.rngresto);}
636
	|	T_MUNION	// map A to B * map A to B -> map A to B
637
		{binop = createBinaryOperator(ExpressionKind.munion);}
638
	|	T_SEQMOD_MAPOVERRIDE	// list of A * map int to A -> list of A or
639
					// map A to B * map A to B -> map A to B
640
		{binop = createBinaryOperator(ExpressionKind.seqmod_mapoverride);}
641
	;
642

    
643
	
644
atomExpression
645
	returns [Expression expr]
646
	@init {
647
		expr = null;
648
	}
649
	:	(unexpr=op_un? (   
650
		     e=identifierExpression
651
		  |  e=constant
652
		  |  e=initializedComplexType 
653
		  |  e=quantifierExpression
654
		  |  T_LPAREN e=expression T_RPAREN		   
655
		     ( 
656
			  (T_POINT 
657
			    idn=T_IDENTIFIER 
658
			    {e = addIdentifierAccessExpression(e,idn);})+
659
			    (res=accessExpression[e] {e=res;})?
660
			| 
661
			  e=accessExpression[e]
662
		      )?
663
		) ('as' cid=T_IDENTIFIER {e=addCastExpression(e,cid);})?
664
		{expr = addUnaryExpression(unexpr,e);}
665
		)
666
		|  ie=T_IF ce=expression T_THEN te=expression T_ELSE ee=expression T_END
667
		{expr = createConditionalExpression(ce,te,ee,ie);}
668
	;	
669
	
670

    
671
quantifierExpression
672
	returns [Quantifier result]
673
	@init {
674
		result = null;
675
	}
676
	: 	t=(T_FORALL | T_EXISTS)
677
		{result = createQuantifierExpression(t);}
678
		(id=T_IDENTIFIER (T_COLON id_type=simpleType {addBoundVarToQuantifierExpression(result,id,id_type);}) 
679
		  (T_COMMA id2=T_IDENTIFIER (T_COLON id_type2=simpleType){addBoundVarToQuantifierExpression(result,id2,id_type2);})*) 
680
		T_COLON T_LPAREN e=expression T_RPAREN
681
		{addExpressionToQuantifier(result,e);}
682
	;
683
	finally
684
		{removeBoundVarsFromResolveStack(result);}
685

    
686
constant
687
	returns [LeafExpression result]
688
	@init {
689
		result = null;
690
	}
691
	: 	T_TRUE  {result = createBoolConstant(true);}
692
	|	T_FALSE {result = createBoolConstant(false);}
693
	|	T_NIL 	{result = createNullPointerConstant();}
694
	|	T_SELF  {result = createSelfPointer();}
695
	| 	t_fl=T_FLOATNUMBER {result = createFloatConstant(t_fl);}
696
	|	t_in=T_INTNUMBER {result = createIntConstant(t_in);}
697
	|	t_l=T_STRINGLITERAL {result = createStringConstant(t_l);}
698
	;
699
	
700
initializedComplexType
701
	returns [Expression result]
702
	@init {
703
		result = null;
704
	}
705
	:	res=initializedListType {result = res;}
706
	|	res=initializedSetType {result = res;}
707
	| 	T_NEW T_LPAREN anid=T_IDENTIFIER 
708
			(
709
				T_COMMA  aname=T_STRINGLITERAL T_RPAREN {result = createNamedObject(anid, aname);}
710
			|	T_RPAREN {result = createObject(anid);}	// constructor call..
711
			)
712
	;
713
	
714
initializedListType
715
	returns [ListConstructor result]
716
	@init {
717
		result = createInitializedList();
718
		pushListVarsOnResolveStack(result); // need this here for list comprehension
719
	}
720
	:	T_LSQPAREN e=expression {addListElement(result,e);} ( 
721
			(T_COMMA e2=expression {addListElement(result,e2);})+ 
722
		| 	listComprehension[result]
723
		)? T_RSQPAREN  
724
	;		
725
	finally
726
		{popListVarsFromResolveStack(result);}
727

    
728
listComprehension [ListConstructor result]
729
	@init{	
730
		result.SetHasComprehension(true);
731
	}
732
	:
733
		T_BAR T_VAR
734
		id=T_IDENTIFIER  T_COLON t1=complexType {addListComprVar(result,id,t1);} 
735
			(T_SEMICOLON id2=T_IDENTIFIER  t2=complexType {addListComprVar(result,id2,t2);})* 
736
		('&'
737
		e=expression {addListComprExpr(result,e);})?
738
	;
739
	
740
initializedSetType
741
	returns[Expression result]
742
	@init {
743
		result = null;
744
	}
745
	:	T_CBRL T_MAPS T_CBRR {result = createEmptyMap();}  // empty map
746
	|	res=initializedSet {result = res;}
747
	;	
748
	
749
initializedSet
750
	returns [Expression result]
751
	@init {
752
		SetConstructor theset = createSet(); 
753
		pushSetVarsOnResolveStack(theset); // need this here for set comprehension
754
		result = theset;
755
	}
756
	:	T_CBRL e1=expression 
757
	        (    			// set constructor; empty set: {nil}
758
			{addToSet(result,e1);}
759
			(T_COMMA e2=expression {addToSet(result,e2);})*			  // set constructor for sets > 1 elem
760
		| 	m=map[result, e1] {result = m;}  // we have a set in the resolution stack, but this should be fine (no syms)
761
		|	{addToSet(result,e1);} setComprehension[(SetConstructor)result]   // set comprehension
762
		) T_CBRR 
763
	;	
764
	finally
765
		{popSetVarsFromResolveStack(theset);}
766
	
767
map[Expression _map, Expression e1]	
768
	returns [Expression result]
769
	@init {
770
		result = null;
771
	}
772
	:	am=T_MAPS e2=expression  {result = createMap(e1,e2,am);}   (T_COMMA e3=expression T_MAPS e4=expression {addToMap(result,e3,e4);})*
773
	;
774

    
775
setComprehension[SetConstructor _set]
776
	@init {
777
		_set.SetHasComprehension(true);
778
	}
779
	:	T_BAR T_VAR id1=T_IDENTIFIER  T_COLON t1=complexType 
780
		{ addSetComprVar(_set, id1, t1); }
781
		(T_SEMICOLON id2=T_IDENTIFIER T_COLON t2=complexType
782
		 { addSetComprVar(_set, id2, t2); })*  
783
		('&'
784
		epx=expression
785
		{ addSetComprExpr(_set,epx); })?
786
	;
787

    
788
identifierExpression
789
	returns [Expression result]
790
	:  	// if next token is a tuple-type then create an initialized tuple!
791
		{isTuple(input.LT(1).getText())}? 		
792
		aName=T_IDENTIFIER T_LPAREN m_params=methodCallParams T_RPAREN
793
		{result = createInitializedTuple(aName,m_params);}
794
	| 	// is some sort of reference
795
		res=reference
796
	  	{result = res;}	
797
	;
798

    
799

    
800
reference 
801
	returns [Expression  result]
802
	@init {
803
		result = null;
804
		init = null;
805
	}
806
	:	{!isTuple(input.LT(1).getText())}? // check that the next token is not a reference to a tuple-type
807
		aName=qualifiedIdentifier {result = aName;}		
808
		(	output=accessExpression[result] {result = output;}
809
			// call expression
810
		|	// variable access or method call that takes no params? (do we allow for that? - answer: no!)
811
		)
812
		( 	pr=T_PRIMED {result = setIdentifierExpressionPrimed(result,pr);} 
813
		 |	
814
		 	('::' T_LPAREN init=expression T_RPAREN)? afold=(T_FOLDLR|T_FOLDRL) T_LPAREN anexpr=expression T_RPAREN 
815
		 	{result = createFoldExpression(result,afold,init,anexpr);}
816
		)?
817
	;
818

    
819
accessExpression[Expression subexpr]
820
	returns [Expression result]
821
	@init{
822
		UnaryOperator newExpr = null;
823
		result = subexpr;
824
	}
825
	:	
826
    		(	tcall=T_LSQPAREN ac=expression T_RSQPAREN 			// access tuples, maps 
827
    			{ result = createTupleMapAccessExpression(result,ac,tcall); } 
828
		|     	bcall=T_LPAREN m_params=methodCallParams T_RPAREN // access method
829
			{ result = createMethodAccessExpression(result,m_params,bcall); }
830
		)+
831
		(	// a[1].c.e()...
832
			(T_POINT 
833
			idn=T_IDENTIFIER 
834
			{result = addIdentifierAccessExpression(result,idn);})+
835
			(res=accessExpression[result] {result=res;})?
836
		)?	
837
	;
838
	
839
qualifiedIdentifier
840
	returns [Expression top]
841
	@init {
842
		IdentifierExpression selfexpr = null;
843
		top = null;
844
	}
845
	:
846
		(self=T_SELF T_POINT		{selfexpr = createSelfIdentifierExpression(self);})? 
847
		idb=T_IDENTIFIER 		{top = createIdentifierAccessExpression(selfexpr,idb);}
848
		(T_POINT idd=T_IDENTIFIER 	{top = addIdentifierAccessExpression(top,idd);})* 
849
	;
850
	
851

    
852
methodCallParams
853
	returns [ArrayList<Expression> result]
854
	@init {
855
		result = new ArrayList<Expression>();
856
	}
857
	:	(expa=expression {result.add(expa);} (T_COMMA expb=expression {result.add(expb);})*)?
858
	;
859

    
860

    
861

    
862
//
863
//  ------------  unary  Operators    ------------ 
864
//
865
	
866
	
867
op_un
868
	returns [UnaryOperator expr]
869
	@init {
870
		expr = null;
871
	}
872
	:	r=op_un_set_list {expr = r;}
873
	|	r2=op_un_map 	{expr = r2;}
874
	|	T_MINUS 	{expr = createUnaryOperator(ExpressionKind.unminus);}
875
	|	T_NOT		{expr = createUnaryOperator(ExpressionKind.not);}
876
	|	T_ABS		{expr = createUnaryOperator(ExpressionKind.abs);}
877
	;	
878

    
879

    
880
op_un_set_list
881
	returns [UnaryOperator expr]
882
	@init {
883
		expr = null;
884
	}
885
	:	T_CARD		// list of A -> int (does not respect dupes, i.e. dupes do not count)
886
		{expr = createUnaryOperator(ExpressionKind.card);}
887
	|	T_DCONC		// list of list of A -> list of A
888
		{expr = createUnaryOperator(ExpressionKind.dconc);}
889
	|	T_DINTER	// list of list of A -> list of A (intersection, does not respect dupes)
890
		{expr = createUnaryOperator(ExpressionKind.dinter);}
891
	|	T_DUNION	// list of list of A -> list of A (union, does not respect dupes)
892
		{expr = createUnaryOperator(ExpressionKind.dunion);}
893
	|	T_ELEMS		// list of A -> list of A (does not respect dupes)
894
		{expr = createUnaryOperator(ExpressionKind.elems);}
895
	|	T_HEAD		// list of A -> A
896
		{expr = createUnaryOperator(ExpressionKind.head);}
897
	|	T_INDS		// list of A -> list of int
898
		{expr = createUnaryOperator(ExpressionKind.inds);}
899
	|	T_LEN		// list of A -> int (dupes count)
900
		{expr = createUnaryOperator(ExpressionKind.len);}
901
	|	T_TAIL		// list of A -> list of A	
902
		{expr = createUnaryOperator(ExpressionKind.tail);}
903
	;
904

    
905

    
906
op_un_map
907
	returns [UnaryOperator expr]
908
	@init {
909
		expr = null;
910
	}
911
	:	T_DOM		// map A to B -> list of A
912
		{expr = createUnaryOperator(ExpressionKind.dom);}
913
	|	T_RNG		// map A to B -> list of B
914
		{expr = createUnaryOperator(ExpressionKind.range);}
915
	|	T_MERGE		// list of map A to B -> map A to B
916
		{expr = createUnaryOperator(ExpressionKind.merge);}
917
	;
918

    
919

    
920

    
921

    
922

    
923

    
924
//
925
//  ==============   LEXER   =================
926
//
927
T_WS  	: (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
928
    	;
929
    	
930
T_COMMENT
931
    	: '/*' .* '*/' {$channel=HIDDEN;}
932
    	;
933
    	
934
LINE_COMMENT
935
    	: '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
936
    	;
937

    
938
T_PRIMED
939
	:	'\'';
940

    
941
T_STRINGLITERAL
942
	:	'"' 
943
		(
944
     			( '"' '"' )=>  '"' 
945
      		|  	~'"'
946
  		)*
947
 		'"'
948
	;
949

    
950

    
951
T_ABORT	:	'abort';
952
T_ACTIONS
953
	:	'actions';
954
T_ASSIGNMENT
955
	:	':=';
956
T_AUTOCONS:	'autocons';
957
T_BAR	:	'|';
958
T_BOOL	:	'bool';
959
T_CBRL	:	'{';
960
T_CBRR	:	'}';
961
T_COLON	:	':';
962
T_COMMA	:	',';
963
//T_CONT	:	'qual';
964
T_CHAR	:	'char';
965
T_CTRL 	:	'ctr';
966
T_SYSTEM
967
	:	'system';
968
T_DO	:	'do';
969
T_ELSE	:	'else';
970
T_END	:	'end';
971
T_EQUAL	:	'=';
972
T_EXISTS	:	'exists';
973
T_FLOAT	:	'float';
974
T_FORALL	:	'forall';
975
T_FALSE 	:	'false';	
976
T_IF	:	'if';
977
T_IN	:	'in';
978
T_INT	:	'int';
979
T_KILL	:	'kill';
980
T_LIST	:	'list';
981
T_LPAREN	:	'(';
982
T_LSQPAREN:	'[';
983
T_MAP	:	'map';
984
T_MAPS	:	'->';
985
T_METHODS
986
	:	'methods';
987
T_NEW	:	'new';
988
T_NIL	:	'nil';
989
T_NONDET	:	'[]';
990
T_OBS	:	'obs';
991
T_OD	:	'od';
992
T_OF	:	'of';
993
T_PRIO	:	'//';
994
T_REQUIRES
995
	:	'requires';
996
T_RPAREN	:	')';
997
T_RSQPAREN:	']';
998
T_SELF	:	'self';
999
T_SET 	:	'set';
1000
T_SEMICOLON
1001
	:	';';
1002
T_STATIC	:	'static';	
1003
T_SKIP	:	'skip';
1004
T_BREAK	:	'break';
1005
T_THEN	:	'then';
1006
T_TRUE  	:	'true';
1007
T_TO	:	'to';
1008
T_TYPES	:	'types';
1009
T_VAR	:	'var';
1010
T_WITH	:	'with';     // for nondet assignment
1011

    
1012

    
1013
//T_ACTION:	'action';
1014

    
1015
//BOOL
1016
T_AND	:	'and';
1017
T_BIIMPLIES
1018
	:	'<=>';
1019
T_IMPLIES
1020
	:	'=>';  //VDM-Style
1021
T_NOT	:	'not'; //VDM-Style
1022
T_NOTEQUAL:	'<>';  //VDM-Style
1023
T_OR	:	'or';
1024

    
1025
//Numeric (equal, not equal same as in BOOL)
1026
T_ABS	:	'abs';
1027
T_DIV	:	'/';
1028
T_GREATER
1029
	:	'>';
1030
T_GREATEREQUAL
1031
	:	'>=';
1032
T_IDIV	:	'div';
1033
T_LESS	:	'<';
1034
T_LESSEQUAL
1035
	:	'<='; //VDM-Style
1036
T_MOD	:	'mod'; //VDM-Style
1037
T_POW	:	'**';
1038
T_PROD	:	'*';
1039
T_DERIV	:	'dt';
1040

    
1041
// set/list
1042
T_CARD	:	'card';
1043
T_CONC	:	'^'; 
1044
T_DCONC	:	'conc';
1045
T_DIFF	:	'\\';
1046
T_DINTER	:	'dinter';
1047
T_DUNION	:	'dunion';
1048
T_ELEMS	:	'elems';
1049
T_HEAD	:	'hd';
1050
T_INDS	:	'inds';
1051
T_INTER	:	'inter';
1052
T_LEN	:	'len'; // differs from T_CARD, as card does not count dupes..
1053
T_SEQMOD_MAPOVERRIDE
1054
	:	'++';
1055
T_SUBSET	:	'subset';
1056
T_TAIL	:	'tl';
1057
T_UNION	:	'union';
1058
T_FOLDLR	
1059
	:	':>:';
1060
T_FOLDRL
1061
	:	':<:';
1062

    
1063

    
1064
// maps
1065
T_DOM	:	'dom';
1066
T_DOMRESBY
1067
	:	'<-:';
1068
T_DOMRESTO
1069
	:	'<:';		
1070
T_RNG	:	'rng';
1071
T_RNGRESBY
1072
	:	':->';
1073
T_RNGRESTO
1074
	:	':>';
1075
T_MERGE	:	'merge';
1076
T_MUNION	:	'munion';
1077

    
1078
T_CONSTS	:	'consts';
1079

    
1080
// numbers
1081

    
1082
T_INFTY	:	(T_MINUS|T_SUM)? 'inf'
1083
	;	
1084

    
1085

    
1086
// INTNUMBER, FLOATNUMBER, RANGETO, T_MINUS, T_PLUS are set within
1087
// FLOAT_OR_INT_OR_RANGE
1088
fragment T_INTNUMBER
1089
	:	;
1090
fragment T_FLOATNUMBER
1091
	:	;
1092
fragment T_RANGETO	
1093
	:	;
1094

    
1095
FLOAT_OR_INT_OR_RANGE
1096
	: 	(T_MINUS|T_SUM)? T_DIGIT+
1097
		( // at this stage, we could face an int, int..int (=range), int.exp (=float), int.exp..int.exp (=float range) etc..
1098
				(T_POINT T_POINT) => {$type=T_INTNUMBER;}
1099
			|	(T_POINT T_DIGIT) => T_POINT T_DIGIT+ (('e'|'E') (T_MINUS|T_SUM)? T_DIGIT+)? {$type=T_FLOATNUMBER;}				
1100
			|	{$type=T_INTNUMBER;}
1101
		)
1102
	|	T_POINT
1103
		( // could be point or range..
1104
				T_POINT {$type=T_RANGETO;}
1105
			| 	      {$type=T_POINT;}
1106
		)
1107
	|	T_MINUS	{$type=T_MINUS;}
1108
	|	T_SUM	{$type=T_SUM;}
1109
	;	
1110

    
1111

    
1112

    
1113
fragment T_MINUS:	'-';
1114
fragment T_SUM	:	'+';
1115
fragment T_POINT:	'.';
1116

    
1117

    
1118

    
1119
// identifiers
1120
T_IDENTIFIER
1121
	:	T_LETTER (T_LETTER|T_DIGIT)* 
1122
	;
1123
	
1124
//T_PRIMEDIDENTIFIER
1125
//	:	T_IDENTIFIER '\'';
1126
	
1127
fragment
1128
T_LETTER
1129
	:	'$'
1130
	|	'A'..'Z'
1131
	|	'a'..'z'
1132
	|	'_'
1133
	;
1134

    
1135
fragment 
1136
T_DIGIT:	'0'..'9';
1137