grammar org.etsi.mts.tdl.ATOLan 
    with org.etsi.mts.tdl.TPLan2
    hidden(WS, ML_COMMENT, SL_COMMENT)

import "platform:/resource/org.etsi.mts.tdl.model/model/structured.ecore" as to
import "platform:/resource/org.etsi.mts.tdl.model/model/tdl.ecore" as tdl

Package returns tdl::Package:
    {tdl::Package}
    'Package'
    name=Identifier 
    '{'
        (^import+=ElementImport)*
    
        //TODO: move to a type of package, similar to group perhaps?
        ('Domain' '{'
           ('annotations' ':' ( packagedElement+=AnnotationType)+ ';' )?
            
            ('pics' ':' ( packagedElement+=PICS)+';' )?
            ('entity' 'types' ':' ( packagedElement+=EntityType)+ ';' )?
            ('entities' ':' ( packagedElement+=Entity)+ ';' )?
            ('event' 'types' ':' ( packagedElement+=EventType)+ ';' )?
            ('events' ':' ( packagedElement+=Event)+ ';' )?
            ('event' 'templates' ':' ( packagedElement+=EventOccurrenceTemplate)+ ';' )?
        '}')?
        ('Data' '{'
            (packagedElement+=DataElement)*
        '}'
        )?
        ('Configuration' '{'
            (packagedElement+=GateType)*
            (packagedElement+=ComponentType)*
            (packagedElement+=TestConfiguration)*
        '}'
        )?
        (packagedElement+=StructuredTestObjective)*
        (packagedElement+=TestPurposeDescription)*
        (nestedPackage+=Group)*
    '}';

TestPurposeDescription returns tdl::TestDescription:
    'Advanced Test Purpose'
    '{'
    //no locally ordered
//        (isLocallyOrdered?='Implementation')?
    
        'TP Id' name=Identifier
//        no formal parameters
//        ('(' formalParameter+=FormalParameter ( "," formalParameter+=FormalParameter)* ')')?
        'Config Id' testConfiguration=[tdl::TestConfiguration|Identifier] 

    //from test objectives
    //either extend TD or add annotations
    //    annotations will need to be expanded to TOs + references
//        'Test objective' description=STRING 
//        ('Reference' objectiveURI+=STRING (',' objectiveURI+=STRING )*)?
    //for PICS - make them extend annotations?
//        ('PICS Selection' picsReference+=FirstPICSReference (picsReference+=PICSReference)*)? 
    //variants?
    
        (behaviourDescription=BehaviourDescription)?
    '}'
    ('with'
    '{'
        (comment+=Comment (comment+=Comment)*)?
        (annotation+=Annotation (annotation+=Annotation)*)?
        ('test' 'objectives' ':' testObjective+=[tdl::TestObjective|Identifier] ( "," testObjective+=[tdl::TestObjective|Identifier])* ';')?
    '}')?
    ;

BehaviourDescription returns tdl::BehaviourDescription:
    behaviour=TOCompoundBehaviour
;

TOCompoundBehaviour returns tdl::CompoundBehaviour:
    block=TOBlock
;

TOBlock returns tdl::Block:
    //no guard
//    ('[' guard+=LocalExpression (',' guard+=LocalExpression)* ']')?
        {tdl::Block} 
        (behaviour+=InitialConditionsBehaviour)? 
        (behaviour+=ExpectedBehaviourBehaviour)? 
        (behaviour+=FinalConditionsBehaviour)? 
;

InitialConditionsBehaviour returns tdl::CompoundBehaviour:
    annotation+=InitialConditionsAnnotation
    ':'
    annotation+=WithAnnotation
    block=AtomicBehaviourBlock
;

ExpectedBehaviourBehaviour returns tdl::CompoundBehaviour:
    annotation+=ExpectedBehaviourAnnotation
    ':'
    block=WhenThenBlock
;

FinalConditionsBehaviour returns tdl::CompoundBehaviour:
    annotation+=FinalConditionsAnnotation
    ':'
    annotation+=WithAnnotation
    block=AtomicBehaviourBlock
;

WhenThenBlock returns tdl::Block:
        (behaviour+=WhenBehaviour) 
        (behaviour+=ThenBehaviour) 
;

WhenBehaviour returns tdl::CompoundBehaviour:
    annotation+=WhenAnnotation
    block=AtomicBehaviourBlock
;

ThenBehaviour returns tdl::CompoundBehaviour:
    annotation+=ThenAnnotation
    block=AtomicBehaviourBlock
;


AtomicBehaviourBlock returns tdl::Block:
    //no guard
//    ('[' guard+=LocalExpression (',' guard+=LocalExpression)* ']')?
        {tdl::Block} 
        '{'
        (behaviour+=AtomicBehaviour)*
        '}'
;

AtomicBehaviour returns tdl::Behaviour:
    Message
    //procedure call
    //action
;

WithAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

WhenAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

ThenAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

InitialConditionsAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

FinalConditionsAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

ExpectedBehaviourAnnotation returns tdl::Annotation:
    //try without prefix
    key=[tdl::AnnotationType|Identifier]
;

Message returns tdl::Message:
    //add qualifier?
    comment+=AndOrQualifier?
    //only one qualifier?
    comment+=ArticleQualifier?
    sourceGate=[tdl::GateReference|IdentifierDot]
    ('sends' | (isTrigger?='triggers')) 
    //TODO: use TDLan notation?
    //TODO: expand to more data uses?
    argument=StaticDataUse
    '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)* ';' )?
    '}')?
//  ';'
    ;

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)?
    '}')?
    ;

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)?
    '}')?
    ;

