// Author(s): Aad Mathijssen
// $Date: 2009-10-16 10:37:13 +0200 (Fri, 16 Oct 2009) $
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// This document describes the internal format of the mCRL2 language and the
// corresponding mu-calculus formulas. Here:
// - the following phases of implementation are distinguised:
//   tc : type checking
//   di : data implementation
//   rft: regular formula translation
// - [+p]/[-p] at the end of a branch means that this branch is added/removed at
//   the end of phase p
// - [.p] at the end of a branch means that this branch is only used in phase p
// - <String> is an arbitrary non-empty string excluding the keywords:
//     sort cons map var eqn act proc init
//     struct List Set Bag
//     lambda whr end
//     delta tau sum allow block hide rename comm
//     val mu nu delay yaled nil
//   Note that this is not as restrictive as user-defined identifiers, which
//   also excludes the following keywords:
//     Bool Pos Nat Int Real
//     true false div mod in forall exists
// - <NumberString> is a string of the format '"0"|("-"?[1-9][0-9]*)'
// - <String> and <NumberString> are represented by a quoted ATermAppl constant
// - the other alphabetical strings within angular brackets are non-terminals
//   that represent all possible branches of their productions
// - for non-terminal N, N*/N+ represents an ATermList with zero/one or more N's
// - each c(a_0, ..., a_n), where c is an alphabetical string, represents an
//   ATermAppl with c as its unquoted head and a_0, ..., a_n as its arguments


//Sort expressions
//----------------

//sort expression
<SortExpr>    ::= <SortId>
                | SortCons(<SortConsType>, <SortExpr>)                   
                | SortStruct(<StructCons>+)                              
                | SortArrow(<SortExpr>+, <SortExpr>)
                | SortUnknown                                            [. tc]
                | SortsPossible(<SortExpr>+)                             [. tc]

//sort identifier
<SortId>       ::= SortId(<String>)

//sort constructor type
<SortConsType> ::= SortList                                             
                 | SortSet                                             
                 | SortBag                                            
                 | SortFSet
                 | SortFBag

//constructor declaration of a structured sort
<StructCons>   ::= StructCons(<String>, <StructProj>*, <StringOrNil>)

//projection declaration of a structured sort
<StructProj>   ::= StructProj(<StringOrNil>, <SortExpr>)

//string or nil
<StringOrNil>  ::= <String>
                 | Nil


//Data expressions
//----------------

//data expression
<DataExpr>     ::= Id(<String>)                                          [- tc]
                 | <DataVarId>                                           [+ tc]
                 | <OpId>                                                [+ tc]
                 | DataAppl(<DataExpr>, <DataExpr>+)
                 | Binder(<BindingOperator>, <DataVarId>+, <DataExpr>) 
                 | Whr(<DataExpr>, <WhrDecl>+)                        

//data variable identifier
<DataVarId>    ::= DataVarId(<String>, <SortExpr>)

//operation identifier
<OpId>         ::= OpId(<String>, <SortExpr>)

//binding operator
<BindingOperator>
               ::= SetBagComp                                            [- tc]
                 | SetComp                                               [+ tc]
                 | BagComp                                               [+ tc]
                 | Forall
                 | Exists
                 | Lambda

//where clause declaration
<WhrDecl>      ::= <IdInit>                                              [- tc]
                 | <DataVarIdInit>                                       [+ tc]

//data variable identifier and initialisation
<DataVarIdInit>::= DataVarIdInit(<DataVarId>, <DataExpr>)

<IdInit>       ::= IdInit(<String>, <DataExpr>)

//Data specifications
//-------------------

//data specification
<DataSpec>     ::= DataSpec(<SortSpec>, <ConsSpec>,
                     <MapSpec>, <DataEqnSpec>)

//sort specification
<SortSpec>     ::= SortSpec(<SortDecl>*)

//constructor specification
<ConsSpec>     ::= ConsSpec(<OpId>*)

//mapping specification
<MapSpec>      ::= MapSpec(<OpId>*)

//data equation specification
<DataEqnSpec>  ::= DataEqnSpec(<DataEqn>*)

//sort declaration
<SortDecl>     ::= <SortId>
                 | SortRef(<String>, <SortExpr>)                     

//data equation
<DataEqn>      ::= DataEqn(<DataVarId>*, <DataExpr>,
                     <DataExpr>, <DataExpr>)

//data expression or nil
<DataExprOrNil>::= <DataExpr>
                 | Nil


//Multiactions
//------------

//multiaction
<MultAct>      ::= MultAct(<ParamIdOrAction>*)

<ParamIdOrAction> ::= <ParamId>                                          [- tc]
                    | <Action>                                           [+ tc]

//parameterised id
<ParamId>      ::= ParamId(<String>, <DataExpr>*)

//Action
<Action>       ::= Action(<ActId>, <DataExpr>*)

//action identifier
<ActId>        ::= ActId(<String>, <SortExpr>*)


//Process expressions
//-------------------

//process expression
<ProcExpr>     ::= <ParamId>                                             [- tc]
                 | IdAssignment(<String>, <IdInit>*)                     [- tc]
                 | <Action>                                              [+ tc]
                 | Process(<ProcVarId>, <DataExpr>*)                     [+ tc]
                 | ProcessAssignment(<ProcVarId>, <DataVarIdInit>*)      [+ tc]
                 | Delta
                 | Tau
                 | Sum(<DataVarId>+, <ProcExpr>)
                 | Block(<String>*, <ProcExpr>)
                 | Hide(<String>*, <ProcExpr>)
                 | Rename(<RenameExpr>*, <ProcExpr>)
                 | Comm(<CommExpr>*, <ProcExpr>)
                 | Allow(<MultActName>*, <ProcExpr>)
                 | Sync(<ProcExpr>, <ProcExpr>)
                 | AtTime(<ProcExpr>, <DataExpr>)
                 | Seq(<ProcExpr>, <ProcExpr>)
                 | IfThen(<DataExpr>, <ProcExpr>)
                 | IfThenElse(<DataExpr>, <ProcExpr>, <ProcExpr>)
                 | BInit(<ProcExpr>, <ProcExpr>)
                 | Merge(<ProcExpr>, <ProcExpr>)
                 | LMerge(<ProcExpr>, <ProcExpr>)
                 | Choice(<ProcExpr>, <ProcExpr>)

//process identifier
<ProcVarId>    ::= ProcVarId(<String>, <SortExpr>*)

//multiaction name
<MultActName>  ::= MultActName(<String>+)

//renaming expression
<RenameExpr>   ::= RenameExpr(<String>, <String>)

//communication expression
<CommExpr>     ::= CommExpr(<MultActName>, <StringOrNil>)


//Process specifications
//----------------------

//process specification
<ProcSpec>     ::= ProcSpec(<DataSpec>, <ActSpec>, <GlobVarSpec>,
                     <ProcEqnSpec>, <ProcInit>)

//action specification
<ActSpec>      ::= ActSpec(<ActId>*)

//global variables
<GlobVarSpec>  ::= GlobVarSpec(<DataVarId>*)

//process equations or linear processes
<ProcEqnSpec>  ::= ProcEqnSpec(<ProcEqn>*)

//process equation
<ProcEqn>      ::= ProcEqn(<ProcVarId>, <DataVarId>*, <ProcExpr>)

//multiaction or delta
<MultActOrDelta>
               ::= <MultAct>
                 | Delta

//process initialisation
<ProcInit>     ::= ProcessInit(<ProcExpr>)


//Linear process specifications
//-----------------------------

//process specification
<LinProcSpec>   ::= LinProcSpec(<DataSpec>, <ActSpec>, <GlobVarSpec>,
                      <LinearProcess>, <LinearProcessInit>)

//process equations or linear processes
<LinearProcess> ::= LinearProcess(<DataVarId>*, <LinearProcessSummand>*)

//Linear process summand
<LinearProcessSummand>
                ::= LinearProcessSummand(<DataVarId>*, <DataExpr>,
                      <MultActOrDelta>, <DataExprOrNil>, <DataVarIdInit>*)

//process initialisation
<LinearProcessInit>
                ::= LinearProcessInit(<DataVarIdInit>*)


//Mu-calculus formulas
//--------------------

//state formula
<StateFrm>     ::= <DataExpr>
                 | StateTrue
                 | StateFalse
                 | StateNot(<StateFrm>)
                 | StateAnd(<StateFrm>, <StateFrm>)
                 | StateOr(<StateFrm>, <StateFrm>)
                 | StateImp(<StateFrm>, <StateFrm>)
                 | StateForall(<DataVarId>+, <StateFrm>)
                 | StateExists(<DataVarId>+, <StateFrm>)
                 | StateMust(<RegFrm>, <StateFrm>)
                 | StateMay(<RegFrm>, <StateFrm>)
                 | StateYaled
                 | StateYaledTimed(<DataExpr>)
                 | StateDelay
                 | StateDelayTimed(<DataExpr>)
                 | StateVar(<String>, <DataExpr>*)
                 | StateNu(<String>, <DataVarIdInit>*, <StateFrm>)
                 | StateMu(<String>, <DataVarIdInit>*, <StateFrm>)

//regular formula
<RegFrm>       ::= <ActFrm>
                 | RegNil                                                [-rft]
                 | RegSeq(<RegFrm>, <RegFrm>)                            [-rft]
                 | RegAlt(<RegFrm>, <RegFrm>)                            [-rft]
                 | RegTrans(<RegFrm>)                                    [-rft]
                 | RegTransOrNil(<RegFrm>)                               [-rft]

//action formula
<ActFrm>       ::= <MultAct>
                 | <DataExpr>
                 | ActTrue
                 | ActFalse
                 | ActNot(<ActFrm>)
                 | ActAnd(<ActFrm>, <ActFrm>)
                 | ActOr(<ActFrm>, <ActFrm>)
                 | ActImp(<ActFrm>, <ActFrm>)
                 | ActForall(<DataVarId>+, <ActFrm>)
                 | ActExists(<DataVarId>+, <ActFrm>)
                 | ActAt(<ActFrm>, <DataExpr>)


//LPS action rename specifications
//--------------------------------

//Action rename rules
<ActionRenameRules>
               ::= ActionRenameRules(<ActionRenameRule>*)

//Action rename rule
<ActionRenameRule>
               ::= ActionRenameRule(<DataVarId>*, <DataExpr>,
                     <ParamIdOrAction>, <ActionRenameRuleRHS>)

//Right-hand side of an action rename rule
<ActionRenameRuleRHS>
               ::= <ParamId>                                             [- tc]
                 | <Action>                                              [+ tc]
                 | Delta
                 | Tau

//Action rename specification
<ActionRenameSpec>
               ::= ActionRenameSpec(<DataSpec>, <ActSpec>, <ActionRenameRules>)


//PBES's
//------

//PBES specification
<PBES>         ::= PBES(<DataSpec>, <GlobVarSpec>, <PBEqnSpec>, <PBInit>)

//parameterized boolean equation specification
<PBEqnSpec>    ::= PBEqnSpec(<PBEqn>*)

//parameterized boolean initialization
<PBInit>       ::= PBInit(<PropVarInst>)

//parameterized boolean equation
<PBEqn>        ::= PBEqn(<FixPoint>, <PropVarDecl>, <PBExpr>)

//fixpoint symbol
<FixPoint>     ::= Mu
                 | Nu

//propositional variable declaration
<PropVarDecl>  ::= PropVarDecl(<String>, <DataVarId>*)

//parameterized boolean expression
<PBExpr>       ::= <DataExpr>
                 | PBESTrue
                 | PBESFalse
                 | PBESNot(<PBExpr>)
                 | PBESAnd(<PBExpr>, <PBExpr>)
                 | PBESOr(<PBExpr>, <PBExpr>)
                 | PBESImp(<PBExpr>, <PBExpr>)
                 | PBESForall(<DataVarId>+, <PBExpr>)
                 | PBESExists(<DataVarId>+, <PBExpr>)
                 | <PropVarInst>

//propositional variable instantiation
<PropVarInst>  ::= PropVarInst(<String>, <DataExpr>*)

//Boolean expressions
//-------------------

// BES specification (equations + initialization)
<BES>          ::= BES(<BooleanEquation>*, <BooleanExpression>)

// boolean equation
<BooleanEquation>   ::= BooleanEquation(<FixPoint>, <BooleanVariable>, <BooleanExpression>)

// boolean variable
<BooleanVariable>   ::= BooleanVariable(<String>)

// boolean expression
<BooleanExpression> ::= BooleanTrue
                      | BooleanFalse
                      | <BooleanVariable>
                      | BooleanNot(<BooleanExpression>)
                      | BooleanAnd(<BooleanExpression>, <BooleanExpression>)
                      | BooleanOr(<BooleanExpression>, <BooleanExpression>)
                      | BooleanImp(<BooleanExpression>, <BooleanExpression>)
