// automatically generated by Xtext
grammar org.etsi.mts.tdl.TDLan2 with org.eclipse.xtext.common.Terminals

import "http://www.eclipse.org/emf/2002/Ecore" as ecore
import "http://www.etsi.org/spec/TDL/1.4.1" as tdl 

Package returns tdl::Package:
	{tdl::Package}
	'Package'
	name=Identifier
	'{'
		(^import+=ElementImport ( ^import+=ElementImport)* )?
		(packagedElement+=PackageableElement ( packagedElement+=PackageableElement)* )?
		(nestedPackage+=Package (nestedPackage+=Package)*)?
	'}'
	(
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
    ;

Action returns tdl::Action:
	Action_Impl | Function;

ActionReference returns tdl::ActionReference:
	'perform' 'action'
	action=[tdl::Action|Identifier]
	('(' actualParameter+=ParameterBinding ( "," actualParameter+=ParameterBinding)* ')' )?
	('on' componentInstance=[tdl::ComponentInstance|Identifier])?
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';'
	;

Action_Impl returns tdl::Action:
	{tdl::Action}
	'Action'
	name=Identifier
	('(' formalParameter+=FormalParameter ( "," formalParameter+=FormalParameter)* ')' )?
	(':' body=String0)?
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

AlternativeBehaviour returns tdl::AlternativeBehaviour:
	'alternatively'
	block+=Block ('or' block+=Block)* 
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
    	(periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
    	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
	'}'
	)?
	;

Annotation returns tdl::Annotation:
	key=[tdl::AnnotationType|Identifier]
	(':' value=String0)?
	(
	'with'
	  '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		(name=Identifier)?
	'}')?
	';';

AnnotationType returns tdl::AnnotationType:
	{tdl::AnnotationType}
	'Annotation'
	name=Identifier
	('with' 
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?	
	';';

AnyValueOrOmit returns tdl::AnyValueOrOmit:
	{tdl::AnyValueOrOmit}
	'*'
	//('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?
	(
	'with'
	  '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
	'}')?
	;

AnyValue returns tdl::AnyValue:
	{tdl::AnyValue}
	name='?'
	//TODO: remove dataTypeAssociation?
	(':' dataType=[tdl::DataType|Identifier])?
	//('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?	
	(
	'with'
	  '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		//('name' name=Identifier)?
	'}')?
	;

ParameterBinding returns tdl::ParameterBinding:
	parameter=[tdl::Parameter|Identifier]
	'=' 
	dataUse=DataUse
	(
	'with'
	  '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
	'}')?
	;

Assertion returns tdl::Assertion:
	{tdl::Assertion}
	'assert'
	condition=DataUse
    ('on' componentInstance=[tdl::ComponentInstance|Identifier])?
	('otherwise' 'set' 'verdict' 'to' otherwise=DataUse)?
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';

Assignment returns tdl::Assignment:
	//TODO: shall be mandatory
	(componentInstance=[tdl::ComponentInstance|Identifier] '->')?
	variable=VariableUse
	'=' 
	expression=DataUse
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';


Behaviour returns tdl::Behaviour:
  TimerStart 
| TimerStop 
| TimeOut 
| Wait 
| Quiescence 
| PeriodicBehaviour 
| AlternativeBehaviour 
| ParallelBehaviour 
| BoundedLoopBehaviour 
| UnboundedLoopBehaviour 
| ConditionalBehaviour 
| CompoundBehaviour 
//| OptionalBehaviour 
| DefaultBehaviour 
| InterruptBehaviour 
| VerdictAssignment 
| Assertion 
| Stop 
| Break 
| Assignment 
| InlineAction 
| ActionReference 
| TestDescriptionReference 
| Interaction
;


BehaviourDescription returns tdl::BehaviourDescription:
	behaviour=Behaviour
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
    '}'
    )?
	
	;


Block returns tdl::Block:
	('[' guard+=LocalExpression (',' guard+=LocalExpression)* ']')?
	'{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('name' name=Identifier)?
		behaviour+=Behaviour ( behaviour+=Behaviour)* 
	'}'
	;

LocalExpression returns tdl::LocalExpression:
	expression=DataUse ('on' scope=[tdl::ComponentInstance|Identifier])? 
	;

LocalLoopExpression returns tdl::LocalExpression:
	expression=DataUse 'times' ('on' scope=[tdl::ComponentInstance|Identifier])? 
	;


MemberReference returns tdl::MemberReference:
	member=[tdl::Member|Identifier] ('[' collectionIndex=DataUse ']')? 
	;

CollectionReference returns tdl::MemberReference:
	'[' collectionIndex=DataUse ']' 
	;


Boolean returns ecore::EBoolean:
	'true' | 'false'
;

BoundedLoopBehaviour returns tdl::BoundedLoopBehaviour:
	'repeat'
	numIteration+=LocalLoopExpression (',' numIteration+=LocalLoopExpression)*
	block=Block
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
        (periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
    	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
    '}'
    )?
	;

Break returns tdl::Break:
	{tdl::Break}
	'break'
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';



Comment returns tdl::Comment:
	'Note'
		(name=Identifier)?
	':'
		body=String0

	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';


ComponentInstance returns tdl::ComponentInstance:
	'create'
	role=ComponentInstanceRole
	name=Identifier
	'of' 'type' type=[tdl::ComponentType|Identifier]
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}'
	)?
	';'
	;

ComponentInstanceBinding returns tdl::ComponentInstanceBinding:
	'bind'
	formalComponent=[tdl::ComponentInstance|Identifier]
	'to' actualComponent=[tdl::ComponentInstance|Identifier]
	('with' '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
	'}')?
	;

enum ComponentInstanceRole returns tdl::ComponentInstanceRole:
	SUT = 'SUT' | Tester = 'Tester';

enum GateTypeKind returns tdl::GateTypeKind:
    Message = 'Message' | Procedure = 'Procedure';


ComponentType returns tdl::ComponentType:
	{tdl::ComponentType}
	'Component' 'Type'
	name=Identifier
	'having' 
	'{'
		(timer+=Timer)*
		(variable+=Variable)* 
		(gateInstance+=GateInstance)* 
	'}'
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	;

CompoundBehaviour returns tdl::CompoundBehaviour:
	block=Block
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
    	(periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
    	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
	'}'
	)?
	;

ConditionalBehaviour returns tdl::ConditionalBehaviour:
    'if'
	block+=Block (=>('else' block+=Block) | (('else' 'if' block+=Block)* ('else' block+=Block)))? 
    (
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
    	(periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
    	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
	'}'
    )?
    ;

Connection returns tdl::Connection:
	'connect'
	endPoint+=GateReference "to" endPoint+=GateReference  
	//('end point' endPointX+=[tdl::GateReference|Identifier])*  
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	    ('as' name=Identifier)?
	'}')?
	';';

DataElementMapping returns tdl::DataElementMapping:
	'Map'
		mappableDataElement=[tdl::MappableDataElement|Identifier]
		('to' elementURI=String0)? 
		'in' dataResourceMapping=[tdl::DataResourceMapping|Identifier]
		('as' name=Identifier)?
		
    ('with'
    '{'
        (parameterMapping+=ParameterMapping)*
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	';';

DataInstance returns tdl::DataInstance:
//	SimpleDataInstance_Impl | StructuredDataInstance | Verdict | TimeLabel;
	SimpleDataInstance_Impl | StructuredDataInstance;


//DataInstanceUse returns tdl::DataInstanceUse:
//	{tdl::DataInstanceUse}
//	dataInstance=[tdl::DataInstance|Identifier]
//	('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?
//	('.' reduction+=[tdl::Member|Identifier])*
//    ('with'
//    '{'
//		('name' name=Identifier)?
//        (comment+=Comment (comment+=Comment)*)?
//        (annotation+=Annotation (annotation+=Annotation)*)?
//    '}')?
//	;


DataInstanceUse returns tdl::DataInstanceUse:
	{tdl::DataInstanceUse}
	(
		//referenced DataInstance, arguments or reduction optional
		(	
			(	
				dataInstance=[tdl::DataInstance|NumberAsIdentifier] | 
				(	dataInstance=[tdl::DataInstance|Identifier]
					(unassignedMember=UnassignedMemberTreatment)?
				)
			)
			(
				('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )
				|
				(	(reduction+=CollectionReference)?
					('.' reduction+=MemberReference)*
				)
			)?
		)
	 	|
	 	//anonymous with data type, arguments mandatory
	 	(
	 		'new' dataType=[tdl::DataType|Identifier]
	 		(unassignedMember=UnassignedMemberTreatment)?
			('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )
		)
	 	|
	 	//anonymous with no data type, arguments mandatory, otherwise AnyValue
	 	(	
	 		(unassignedMember=UnassignedMemberTreatment)?
	 		('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )	
	 	)
	) 
    ('with'
    '{'
		('name' name=Identifier)?
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	;


DataResourceMapping returns tdl::DataResourceMapping:
	{tdl::DataResourceMapping}
	'Use'
	(resourceURI=String0)?
	('as' name=Identifier)?
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

DataType returns tdl::DataType:
	SimpleDataType_Impl | StructuredDataType | Time | ProcedureSignature | CollectionDataType;


ProcedureSignature returns tdl::ProcedureSignature:
    {tdl::ProcedureSignature}
    //'Structured' 'Data' 'Type'
    'Signature'
    name=Identifier
    ('(' parameter+=ProcedureParameter ( "," parameter+=ProcedureParameter)* ')')?
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
    ';';

ProcedureParameter returns tdl::ProcedureParameter:
    kind=ParameterKind
    name=Identifier
    'of' 'type'
    dataType=[tdl::DataType|Identifier]
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?;

enum ParameterKind returns tdl::ParameterKind:
    In = 'In' | Out = 'Out' | Exception = 'Exception';


CollectionDataType returns tdl::CollectionDataType:
    {tdl::CollectionDataType}
    //'Structured' 'Data' 'Type'
    'Collection'
    name=Identifier
    'of' 'type'
    itemType=[tdl::DataType|Identifier]
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
    ';';

CollectionDataInstance returns tdl::CollectionDataInstance:
    {tdl::CollectionDataInstance}

    dataType=[tdl::DataType|Identifier]
    name=Identifier
    'containing' '{' 
        (item+=StaticDataUse ("," item+=StaticDataUse)*)?
     
    '}'
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
    ';'
    ;


DataUse returns tdl::DataUse:
	DataInstanceUse | FunctionCall | PredefinedFunctionCall | FormalParameterUse | TimeLabelUse | VariableUse | AnyValue | AnyValueOrOmit | OmitValue;

DefaultBehaviour returns tdl::DefaultBehaviour:
	'default'
	('on' guardedComponent=[tdl::ComponentInstance|Identifier])?
	block=Block
	(
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
	'}')?;

Identifier returns ecore::EString:
	ID
;

PredefinedIdentifierBinary returns ecore::EString:
    '+' | '-' | '*' | '/' | 'mod' 
  | '>' | '<' | '>=' | '<=' | '>='
  | '==' | '!=' | 'and' | 'or' | 'xor'
;

PredefinedIdentifierNot returns ecore::EString:
    'not'
;

PredefinedIdentifierSize returns ecore::EString:
    'size'
;


IdentifierDot returns ecore::EString:
	ID '.' ID
;


ElementImport returns tdl::ElementImport:
	{tdl::ElementImport}
	'Import'
	(	'all'
		|
		(importedElement+=[tdl::PackageableElement|Identifier] ( "," importedElement+=[tdl::PackageableElement|Identifier])*)
	)
	'from' importedPackage=[tdl::Package|Identifier]
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		(name=Identifier)?
	'}')?
	';';


ExceptionalBehaviour returns tdl::ExceptionalBehaviour:
	DefaultBehaviour | InterruptBehaviour;

Function returns tdl::Function:
	'Function'
	name=Identifier
	'(' (formalParameter+=FormalParameter ( "," formalParameter+=FormalParameter)* )? ')'
	'returns' 
	returnType=[tdl::DataType|Identifier]
	(':' body=String0)?
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

FunctionCall returns tdl::FunctionCall:
	'instance' 'returned' 'from'
	function=[tdl::Function|Identifier] 
	'('
	(argument+=ParameterBinding ( "," argument+=ParameterBinding)*)?
	')'
	(reduction+=CollectionReference)?
	('.' reduction+=MemberReference)*
	('with'
	'{'
		('name' name=Identifier)?
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	;

PredefinedFunction returns tdl::PredefinedFunction:
    'Predefined'
    (name=PredefinedIdentifierBinary
        | name=PredefinedIdentifierNot
        | name=PredefinedIdentifierSize
    )
    ';'
    ;


PredefinedFunctionCall returns tdl::PredefinedFunctionCall:
    PredefinedFunctionCallSize | PredefinedFunctionCallNot | PredefinedFunctionCallBinary
    ;

PredefinedFunctionCallSize returns tdl::PredefinedFunctionCall:
    function=[tdl::PredefinedFunction|PredefinedIdentifierSize] 
    '('
    actualParameters+=DataUse
    ')'
    ;


PredefinedFunctionCallNot returns tdl::PredefinedFunctionCall:
    function=[tdl::PredefinedFunction|PredefinedIdentifierNot] 
    '('
    actualParameters+=DataUse
    ')'
    ;

PredefinedFunctionCallBinary returns tdl::PredefinedFunctionCall:
    '('
    actualParameters+=DataUse 
    function=[tdl::PredefinedFunction|PredefinedIdentifierBinary] 
    actualParameters+=DataUse
    ')'
    ;



GateInstance returns tdl::GateInstance:
	{tdl::GateInstance}
	'gate'
	name=Identifier
	'of' 'type' type=[tdl::GateType|Identifier]
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

GateReference returns tdl::GateReference:
	component=[tdl::ComponentInstance|Identifier]
	'.'
	gate=[tdl::GateInstance|Identifier]
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=IdentifierDot)?
	'}')?
	;


GateType returns tdl::GateType:
    (kind=GateTypeKind)?
	'Gate' 'Type'
	name=Identifier
	'accepts'
		dataType+=[tdl::DataType|Identifier] ( "," dataType+=[tdl::DataType|Identifier])*  
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	';';

InlineAction returns tdl::InlineAction:
	'perform' 'action' ':'
	body=String0
	('on' componentInstance=[tdl::ComponentInstance|Identifier])?
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)? //USE FOR STEPS?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
    '}')?
	';';

Interaction returns tdl::Interaction:
	Message | ProcedureCall
	;

Message returns tdl::Message:
	sourceGate=[tdl::GateReference|IdentifierDot]
	('sends' | (isTrigger?='triggers')) 
	argument=DataUse
	'to' 
	target+=TargetMessage ( "," target+=TargetMessage)* 
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)? //USE FOR STEPS?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';'
	;

ProcedureCall returns tdl::ProcedureCall:
    sourceGate=[tdl::GateReference|IdentifierDot]
    'calls' 
    signature=[tdl::ProcedureSignature|Identifier]
    '('argument+=ParameterBinding ("," argument+=ParameterBinding)*')'
    'on' 
    target+=TargetProcedure
    //TODO: add support for responses
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
        ('name' name=Identifier)? //USE FOR STEPS?
        ('time' 'label' timeLabel=TimeLabel)?
        ('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
    '}')?
    ';'
    ;

Trigger returns ecore::EBooleanObject :
	'triggers'
;


InterruptBehaviour returns tdl::InterruptBehaviour:
	'interrupt'
	('on' guardedComponent=[tdl::ComponentInstance|Identifier])?
	block=Block
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
	'}')?;

MappableDataElement returns tdl::MappableDataElement:
//	SimpleDataType_Impl | SimpleDataInstance_Impl | StructuredDataType | StructuredDataInstance | Action_Impl | Function | Verdict | Time | TimeLabel;
	SimpleDataType_Impl | SimpleDataInstance_Impl | StructuredDataType | StructuredDataInstance | Action_Impl | Function | Time;

Member returns tdl::Member:
	(isOptional?='optional')?
	name=Identifier
	'of' 'type'
	dataType=[tdl::DataType|Identifier]
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?;

Optional returns ecore::EBoolean :
	'optional' | 'mandatory' 
;

MemberAssignment returns tdl::MemberAssignment:
	member=[tdl::Member|Identifier]
	'=' 
	memberSpec=StaticDataUse
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
	'}')?;

ParameterMapping returns tdl::ParameterMapping:
	parameter=[tdl::Parameter|Identifier]
	('mapped' 'to' parameterURI=String0)?
	('as' name=Identifier)?
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

OmitValue returns tdl::OmitValue:
	{tdl::OmitValue}
	'omit'
    (
    'with'
    '{'
		('argument' '{' argument+=ParameterBinding ( "," argument+=ParameterBinding)* '}' )?
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
	'}')?;


//OptionalBehaviour returns tdl::OptionalBehaviour:
//	'optionally'
//	block=Block
//	(
//    'with'
//    '{'
//	    (comment+=Comment (comment+=Comment)*)?
//		(annotation+=Annotation (annotation+=Annotation)*)?
//		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
//		('name' name=Identifier)?
//	'}')?
//	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
//	(periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
//	';'
//	;
	


PackageableElement returns tdl::PackageableElement:
//	AnnotationType | TestObjective | DataResourceMapping | DataElementMapping | SimpleDataType_Impl | SimpleDataInstance_Impl | StructuredDataType | StructuredDataInstance | Action_Impl | Function | Verdict | ComponentType | GateType | Time | TimeLabel | TestConfiguration | TestDescription;
	AnnotationType | TestObjective | DataResourceMapping | DataElementMapping | SimpleDataType_Impl | SimpleDataInstance_Impl | StructuredDataType | StructuredDataInstance | Action_Impl | Function | ComponentType | GateType | Time | TestConfiguration | TestDescription | CollectionDataType | CollectionDataInstance | ProcedureSignature | PredefinedFunction;

ParallelBehaviour returns tdl::ParallelBehaviour:
	'run' block+=Block ('in' 'parallel' 'to' block+=Block)* 
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
        (periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
        (exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
	'}'
	)?
	;

Parameter returns tdl::Parameter:
	Member | FormalParameter;

FormalParameter returns tdl::FormalParameter:
    name=Identifier
    'of' 'type'
    dataType=[tdl::DataType|Identifier]
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?;

TimeLabelUse returns tdl::TimeLabelUse:
	'time' 'label' timeLabel=[tdl::TimeLabel|Identifier]
	('.' kind=TimeLabelUseKind)?
	//('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?
	//( "." reduction+=[tdl::Member|Identifier])*
    (
    'with'
    '{'
		('argument' '{' argument+=ParameterBinding ( "," argument+=ParameterBinding)* '}' )?
		('name' name=Identifier)?
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?;


enum TimeLabelUseKind returns tdl::TimeLabelUseKind:
    Last = 'last' | Previous = 'previous' | First = 'first';


FormalParameterUse returns tdl::FormalParameterUse:
	'parameter'
	parameter=[tdl::FormalParameter|Identifier]
	('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?
	(reduction+=CollectionReference)?
	( "." reduction+=MemberReference)*
    (
    'with'
    '{'
		('name' name=Identifier)?
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?;


PeriodicBehaviour returns tdl::PeriodicBehaviour:
	'every'
	(period+=LocalExpression (',' period+=LocalExpression)*)
    block=Block
    (
    'with'
    '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
    '}'
    )?;

Quiescence returns tdl::Quiescence:
	('component' componentInstance=[tdl::ComponentInstance|Identifier] | 'gate' gateReference=[tdl::GateReference|IdentifierDot])
	'is' 'quiet' 'for'
	period=DataUse 
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';

//Real returns Real:
//	'-'? INT+'.'INT+
//;
//


SimpleDataInstance_Impl returns tdl::SimpleDataInstance:
	dataType=[tdl::DataType|Identifier]
	(name=Identifier | name=NumberAsIdentifier)
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';'
	;

SimpleDataType_Impl returns tdl::SimpleDataType:
	{tdl::SimpleDataType}
	//'Simple' 'Data' 'Type'
	'Type'
	name=Identifier
	 (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	';'
	;		

StaticDataUse returns tdl::StaticDataUse:
	DataInstanceUse | AnyValue | AnyValueOrOmit | OmitValue;

Stop returns tdl::Stop:
	{tdl::Stop}
	'terminate'
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
	
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';

String0 returns ecore::EString:
	STRING
;


enum UnassignedMemberTreatment returns tdl::UnassignedMemberTreatment:
	AnyValue = '?' | AnyValueOrOmit = '*';


StructuredDataInstance returns tdl::StructuredDataInstance:
	{tdl::StructuredDataInstance}
	dataType=[tdl::DataType|Identifier]
	name=Identifier
	(unassignedMember=UnassignedMemberTreatment)?
	'('( memberAssignment+=MemberAssignment (',' memberAssignment+=MemberAssignment)*  )?')'		
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';'
	;

StructuredDataType returns tdl::StructuredDataType:
	{tdl::StructuredDataType}
	//'Structured' 'Data' 'Type'
	'Type'
	name=Identifier
	('(' member+=Member ( "," member+=Member)* ')')?
   	(
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
    ';';

TargetMessage returns tdl::Target:
	targetGate=[tdl::GateReference|IdentifierDot]
	//TODO: check what the correct syntax shall be
	(valueAssignment+=ValueAssignmentMessage)?
   	(
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
		('name' name=Identifier)?
    '}')?
    ;

TargetProcedure returns tdl::Target:
    targetGate=[tdl::GateReference|IdentifierDot]
    //TODO: check what the correct syntax shall be
    (valueAssignment+=ValueAssignmentProcedure ("," valueAssignment+=ValueAssignmentProcedure)*)?
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('name' name=Identifier)?
    '}')?
    ;


ValueAssignmentMessage returns tdl::ValueAssignment:
    //TODO: check what the correct syntax shall be
    'where' 'it' 'is' 'assigned' 'to' variable=[tdl::Variable|Identifier]
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('name' name=Identifier)?
    '}')?
    ;

ValueAssignmentProcedure returns tdl::ValueAssignment:
    //TODO: check what the correct syntax shall be
    'where' parameter=[tdl::Parameter|Identifier] 'is' 'assigned' 'to' variable=[tdl::Variable|Identifier]
    
    (
    'with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('name' name=Identifier)?
    '}')?
    ;


TestConfiguration returns tdl::TestConfiguration:
	'Test' 'Configuration'
		name=Identifier
	'{'
		componentInstance+=ComponentInstance (componentInstance+=ComponentInstance)* 
		connection+=Connection (connection+=Connection)* 
	'}'
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	;

TestDescription returns tdl::TestDescription:
	'Test' 'Description'
		(isLocallyOrdered?='Implementation')?
	
		name=Identifier
		('(' formalParameter+=FormalParameter ( "," formalParameter+=FormalParameter)* ')')?
		'uses' 'configuration' testConfiguration=[tdl::TestConfiguration|Identifier] 
		(behaviourDescription=BehaviourDescription | ';')
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
    '}')?
	;

TestDescriptionReference returns tdl::TestDescriptionReference:
	'execute'
	testDescription=[tdl::TestDescription|Identifier]
	('(' actualParameter+=ParameterBinding ( "," actualParameter+=ParameterBinding)* ')' )?
	('with'
	  '{'
		('bindings' '{' componentInstanceBinding+=ComponentInstanceBinding ( "," componentInstanceBinding+=ComponentInstanceBinding)* '}' )?
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
	
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';';

TestObjective returns tdl::TestObjective:
	{tdl::TestObjective}
	'Test' 'Objective'
		(name=Identifier)?
	'{'
		('from' ':' objectiveURI+=String0 ';' ( 'from' ':' objectiveURI+=String0 ';')* )?
		('description' ':' description=String0 ';')?
	'}'
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	;


Time returns tdl::Time:
	{tdl::Time}
	'Time'
	name=Identifier
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	';';

TimeConstraint returns tdl::TimeConstraint:
		(name=Identifier)?
		timeConstraintExpression=DataUse
		('with'
		'{'
			(comment+=Comment (comment+=Comment)*)?
			(annotation+=Annotation (annotation+=Annotation)*)?
		'}')?
	;

TimeLabel returns tdl::TimeLabel:
	name=Identifier
//	'in' 
//	dataType=[tdl::DataType|Identifier]
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
    '}')?
	';';

TimeOut returns tdl::TimeOut:
	componentInstance=[tdl::ComponentInstance|Identifier]
	'.'	
	timer=[tdl::Timer|Identifier]
	'times' 'out'
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';'
	;

Timer returns tdl::Timer:
	{tdl::Timer}
	'timer'
	name=Identifier
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';


TimerStart returns tdl::TimerStart:
	'start'
	componentInstance=[tdl::ComponentInstance|Identifier]
	'.'
	timer=[tdl::Timer|Identifier]
	'for'
	period=DataUse
	('with' 
	 '{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
		('name' name=Identifier)?
	'}')?
	';'
	;

TimerStop returns tdl::TimerStop:
	'stop'
	componentInstance=[tdl::ComponentInstance|Identifier]
	'.'
	timer=[tdl::Timer|Identifier]
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';'
	;


UnboundedLoopBehaviour returns tdl::UnboundedLoopBehaviour:
	'repeat'
	block=Block
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
    	(periodic+=PeriodicBehaviour ( periodic+=PeriodicBehaviour)* )?
    	(exceptional+=ExceptionalBehaviour ( exceptional+=ExceptionalBehaviour)*)?
	'}'
	)?
	;

Variable returns tdl::Variable:
	'variable'
	name=Identifier
	'of' 'type'
	dataType=[tdl::DataType|Identifier]
	('with' 
	'{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	';';

VariableUse returns tdl::VariableUse:
	//TODO: try to adjust syntax so that -> is not necessary
	componentInstance=[tdl::ComponentInstance|Identifier]
	'->'
	variable=[tdl::Variable|Identifier]
	('(' argument+=ParameterBinding ( "," argument+=ParameterBinding)* ')' )?
	(reduction+=CollectionReference)?
	("." reduction+=MemberReference)*
	('with' 
	'{'
		('name' name=Identifier)?
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
	'}')?
	;


//Verdict returns tdl::Verdict:
//	//'verdict'
//	(	(dataType=[tdl::DataType|PredefinedVerdict] name=Identifier)
//		| 
//		('Verdict' name=Identifier 'of type' dataType=[tdl::DataType|Identifier])
//	)
//    ('with'
//    '{'
//        (comment+=Comment (comment+=Comment)*)?
//        (annotation+=Annotation (annotation+=Annotation)*)?
//    '}')?
//    ';'
//	;


VerdictAssignment returns tdl::VerdictAssignment:
	'set' 'verdict' 'to'
	verdict=DataUse
	(
	'with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
	'}')?
	';'
	;

Wait returns tdl::Wait:
	( 'component' componentInstance=[tdl::ComponentInstance|Identifier])
	'waits' 'for'
	period=DataUse
	('with'
	'{'
		(comment+=Comment (comment+=Comment)*)?
		(annotation+=Annotation (annotation+=Annotation)*)?
		('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
		('name' name=Identifier)?
		('time' 'label' timeLabel=TimeLabel)?
		('time' 'constraints' ':' timeConstraint+=TimeConstraint ( "," timeConstraint+=TimeConstraint)* ';' )?
		
	'}')?
	';';
	
NumberAsIdentifier returns ecore::EString:
    '-'? INT ('.' INT)?;
	