/*Copyright 2009--2017 Rene Vestergaard
 * 
 * This file is part of CEqEA. 
 * 
 * CEqEA is free software: you can redistribute it and/or modify it under 
 * the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CEqEA is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public 
 * License along with CEqEA, possibly as <CEqEA-dir>/COPYING.  
 * If not, see <http://www.gnu.org/licenses/>. 
 */
 

parseSyntax	
  : (cond? sentence SNTNC_CLSE)* EOF										
  ;

cond	
  : COND PAR_OPEN rglt (LSS_THN LSS_THN|LSS_EQ|EQUAL|GRT_EQ|GRT_THN GRT_THN) rglt PAR_CLSE  	
  ;
  
sentence
  : presentation
  | directive 
  | abstraction
  | modalityDefault
  | schema
  | rgltMacro
  | mutualExcl
  | influence
  | seed
  | ENDCOND										
  ;


/*==================*
 * specialist stuff *
 *==================*/
presentation
  : DGRM_FILTER	ASSIGN	(SQNC_OPEN 
  				NMBR COMMA NMBR	
  			 SQNC_CLSE)*		
  ;
  	
  	
/*==============*
 * MIG preamble *
 *==============*/
directive
  : RESIDTN	ASSIGN 	( 				
  			| ( LEAST_FP | WELLFND )	
  			| ( GREAT_FP | CIRCLR ) 	
  			)				
  | EXO_INF		        
  | WARN_MISS			
  | PREINHB					
  | STT_REPT				
  ;
  

abstraction
  : CATGRS 	ASSIGN	(ABSTR name)*			
  | FLTR (LSS_THN (RGLT|SUBJ)* GRT_THN)?
		ASSIGN	(ABSTR name)*				
  ;



modalityDefault
  : (TRMNTN|CSTN|MDTN|RGLTN|INSTNTTN|SLTN|CONNECT|CHANNEL|SILENCE|EXPIRE)
  		(LSS_THN (SCHM|INFL|SEED) GRT_THN)? 
  		ASSIGN mdltChar*	
  ;
  
/*mdltChar is a technical notion that is used for disambiguation 
 *--it should not be read in its own right; see instead CEq_c_modalities
 *--COMMA receives special treatment: is suppressed from hereon, i.e., may be used freely*/
mdltChar
  : ~(SNTNC_CLSE|ACTV_CLSE|SPPRSS|EXCL|COL_SEP|EXOGENIC|ENDOGENIC|NON_RGLT|NON_SUBJ|ASSIGN|COMMA) 
  | COMMA
  ;


/*========================================================================*
 * symbol table maintenance and access                                    *
 * --name occurs multiple times in BNF                                    *
 * --each is different for parser, not user                               *
 *                                                                        *
 * a user-specifiable name is one of                                      *
 * - NAME [any sequence of non-reserved characters, except a MIG keyword] *
 * - NMBR [a number, with first digit not 0]                              *
 * - ""   [two quotation marks, corresponding to the empty name]          *
 * - any MIG keyword                                                      *
 *========================================================================*/
name 
  : ( NAME		
    | NMBR		
    | QUOTTN QUOTTN	
    | ( DGRM_FILTER
      | WARN_MISS
      | EXO_INF
      | RESIDTN
      | LEAST_FP
      | GREAT_FP
      | CIRCLR
      | WELLFND
      | PREINHB
      | STT_REPT
      | CATGRS
      | FLTR
      | CHANNEL
      | COND
      | ENDCOND
      | TRMNTN
      | APPRX
      | ENDPT
      | CSLSS
      | CSTN
      | PUSH
      | PULL
      | PUSHPULL
      | MDTN
      | RESID
      | STPWS
      | EXPLCT
      | DNMC
      | IMPLCT
      | RGLTN
      | CHMSTRY
      | EXTRINSIC
      | INTRINSIC
      | INCIDENTL
      | INSTNTTN
      | CHRNT
      | MIXED
      | SLTN
      | EMPTY
      | FIXED
      | APPEAR
      | APPEAR_OK
      | VANISH
      | VANISH_OK
      | CHANGE
      | CHANGE_OK
      | SCHM
      | INFL
      | SEED
      | DFLT
      | MDTR
      | INHB
      | RGLT
      | SUBJ
      | DRCT
      | INDRCT
      | SITU
      | RCTN
      | SLVNT
      | SRCE
      | SINK
      | SPPRSS
      | EXOGENIC
      | ENDOGENIC
      | NON_RGLT
      | NON_SUBJ
      | CONNECT
      | EXCL
      | MUTEXCL
      | INCOM
      | OUTGO
      | NO_INCOM
      | NO_OUTGO
      | SILENCE
      | EXPIRE
      ) 
    ) 
  ;

schmReference 	 		
  : name	
  ;
	
stateReference		
  : name 	
  ;



/*================*
 * schema related *
 *================*/
schema	
  : (ABSTR name LVLING)? name	
   	DOT	 ( instance
    	  	 | (ABSTR name LVLING instance)+
    	  	 )
    	(COL_SEP ( EXOGENIC	
	  	 | ENDOGENIC	
	  	 | NON_RGLT	
	  	 | NON_SUBJ	
	  	 | mdltChar
	  	 )*
	)? 							
  | SPPRSS (ABSTR name LVLING)? name nonClse*		
  ;

/*nonClse is a technical notion, not to be read in own right
 *--it permits the use of SPPRSS in an otherwise ill-formed schema declaration*/
nonClse
  : ~SNTNC_CLSE
  ;


//States
instance
  : stateAlts? (SQNC_CLSE SQNC_CLSE stateActvt* SQNC_OPEN SQNC_OPEN)?			
  ;

stateSqnc	
  : (/*not in schema declarations*/ (ABSTR name | COMMA)+ LVLING)? stateAlts+ 	
  ;
  
stateAlts	
  : stateUnit (SUBJ_ALT stateUnit)*			
  ;

stateUnit	
  : /*only in schema declarations*/ stateActvt
  | /*not in schema declarations*/ subjColl 			
  | SQNC_OPEN stateSqnc SQNC_CLSE					
  ;

stateActvt	
  : stateDecl
  | ACTV_OPEN stateDecl ACTV_CLSE
  ;

stateDecl		
  : name 												
  ;

 
/*===================*
 * regulation macros *
 *===================*/
rgltMacro
  : MACRO NAME (LSS_THN (MACRO NAME | COMMA)* GRT_THN)? 
  	(PAR_OPEN macroParam (COMMA macroParam)* PAR_CLSE)?
    ASSIGN (rglt (EXCL rgltDsj)?)?
  ;
  
macroParam	
  : SHARP NAME					
  ;
  
mutualExcl	
 : MUTEXCL PAR_OPEN (MACRO name | COMMA)* PAR_CLSE				
 ;  
  
/*
 *==================*
 * influence related*
 *==================*/
influence	
  : (PSTV|NGTV)
  	coInhbt?
  	contravariance?
  	COL_SEP stateSqnc
  	COL_SEP rglt
    	(COL_SEP mdltChar*)?		
  ;

contravariance	
  : RGLT_STRONG	
    coInhbt?
    (ACTV_OPEN	rglt?
    	(COL_SEP COL_SEP? mdltChar*)? 
     ACTV_CLSE)?									
  ;
  
coInhbt
  : GRT_THN (MACRO NAME | COMMA)* LSS_THN			
  ;

//Subjects
subjColl	
  : schmReference		
  | schmReference DOT	subjState
  | schmReference DOT 	SQNC_OPEN subjState+ SQNC_CLSE 					
  | schmReference DOT 	SQNC_OPEN
  				(subjState (SHARP NMBR)?)?
  				RANGE 
  				(subjState (SHARP NMBR)?)?
  			SQNC_CLSE												
  ;

subjState		 
  : stateReference 
  ;

  
//Regulation
rglt
  : rgltDsj (RGLT_INHBTN rgltDsj)?		
  ;


//Mediators
rgltDsj
  : rgltCnj (RGLT_DSJNCT rgltCnj)* 	
  ;
  
rgltCnj	
  : rgltStr (RGLT_CNJNCT rgltStr)*				
  ;

rgltStr
  : rgltOrdr contravariance?			
  ;
  
rgltOrdr	
  : RGLT_INDRCT* rgltRng	
  ;

rgltRng			
  : (rgltUnit ((SHARP NMBR)? (RANGE|PSTV|PAR_OPEN PSTV PAR_CLSE) (?rgltUnit (SHARP NMBR)?)?)? | (RANGE|PSTV|PAR_OPEN PSTV PAR_CLSE) rgltUnit (SHARP NMBR)?)	
  ;

rgltUnit	
  : macroExp
  | rgltSchema
  | /*only if in macro definition*/ SHARP NAME					
  | (MIN|MAX) (RGLT_DSJNCT | RGLT_CNJNCT) PAR_OPEN rglt (COMMA rglt)* PAR_CLSE 
  | cond PAR_OPEN rglt PAR_CLSE (PAR_OPEN rglt PAR_CLSE)?				  	
  | PAR_OPEN rglt PAR_CLSE
  ;

macroExp	
  : MACRO MACRO? NAME (PAR_OPEN macroArg (COMMA macroArg)* PAR_CLSE)? /*2nd MACRO means "strip !s"*/	
  ;
  
macroArg	
  : rglt 
  ;

rgltSchema
  : schmReference			
  | schmReference DOT rgltState
  | schmReference DOT ACTV_OPEN rgltState+ ACTV_CLSE						
  ;

rgltState			
  : stateReference		
  ;



/*=============*/
/*seeds related*/
/*=============*/
seed_fragment	/*COMMA is suppressed from hereon, i.e., may be used freely*/
  : QUOTTN (name DOT name|COMMA)+ QUOTTN (CHANNEL PAR_OPEN name PAR_CLSE)? (COL_SEP (EXCL|mdltChar*))?
  ; 

seed
  : seed_fragment		
  ;