// Author(s): Aad Mathijssen, Wieger Wesselink
// $Date: 2013-11-24 12:30:39 +0100 (Sun, 24 Nov 2013) $
//
// 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:
// - <String> is an arbitrary non-empty string excluding the mCRL2 keywords
// - <StringOrEmpty> is a <String> or the empty string
// - <NumberString> is a string of the format '"0"|("-"?[1-9][0-9]*)'
// - <String>, <StringOrEmpty> and <NumberString> are terminals
// - 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>)
                | UntypedSortUnknown
                | UntypedSortsPossible(<SortExpr>+)

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

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

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

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

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

//data expression
<DataExpr>     ::= <DataVarId>
                 | <OpId>
                 | DataAppl(<DataExpr>, <DataExpr>+)
                 | Binder(<BindingOperator>, <DataVarId>+, <DataExpr>)
                 | Whr(<DataExpr>, <WhrDecl>+)
                 | UntypedIdentifier(<String>)

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

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

//binding operator
<BindingOperator>
               ::= Forall
                 | Exists
                 | SetComp
                 | BagComp
                 | Lambda
                 | UntypedSetBagComp

//where clause declaration
<WhrDecl>      ::= <DataVarIdInit>
                 | <UntypedIdentifierAssignment>

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

<UntypedIdentifierAssignment>       ::= UntypedIdentifierAssignment(<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(<SortId>, <SortExpr>)

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

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


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

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

//untyped multiaction
<UntypedMultAct> ::= UntypedMultAct(<UntypedAction>*)

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

//untyped action
<UntypedAction> ::= UntypedAction(<String>, <DataExpr>*)

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


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

//process expression
<ProcExpr>     ::= <Action>
                 | Process(<ProcVarId>, <DataExpr>*)
                 | ProcessAssignment(<ProcVarId>, <DataVarIdInit>*)
                 | 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>)
                 | UntypedParamId(<String>, <DataExpr>*)
                 | UntypedProcessAssignment(<String>, <UntypedIdentifierAssignment>*)

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

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

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

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


//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
                 | RegSeq(<RegFrm>, <RegFrm>)
                 | RegAlt(<RegFrm>, <RegFrm>)
                 | RegTrans(<RegFrm>)
                 | RegTransOrNil(<RegFrm>)

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

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

<ParamIdOrAction> ::= <UntypedAction>
                    | <Action>

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

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

//Right-hand side of an action rename rule
<ActionRenameRuleRHS>
               ::= <UntypedAction>
                 | <Action>
                 | 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>*, <Number>)

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

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

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

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

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