Grammar

transformation
	:	"TRANSFORMATION" ID 
		(	formals 
		|	COLON vardecls ARROW vardecls 
		) 
		( body )* EOF 
	;


formals
	:	LBRACK 
		(	vardecls 
		|	
		) 
		RBRACK 
	;


vardecls
	:	vardecl ( COMMA vardecl )* 
	;


body
	:	importDecl 
	|	classDecl 
	|	map 
	|	patternDefn 
	|	templateDefn 
	|	trule 
	;


importDecl
	:	"IMPORT" URITOK 
	;


classDecl
	:	"CLASS" ID 
		(	"EXTENDS" superClasses 
		|	
		) 
		(	LBRACE ( simpleTypeLiteral ID SEMI )* RBRACE 
		|	
		) 
		SEMI 
	;


map
	:	"MAP" ID LBRACE 
		(	map_pairs 
		|	
		) 
		RBRACE SEMI 
	;


patternDefn
	:	"PATTERN" pname formals 
		(	"FORALL" ranges 
		|	
		) 
		(	"WHERE" conjunct 
		|	
		) 
		SEMI 
	;


templateDefn
	:	"TEMPLATE" pname formals targetClauses SEMI 
	;


trule
	:	(	"ABSTRACT" 
		|	
		) 
		"RULE" rname 
		(	formals 
		|	
		) 
		( relatedRules )* 
		(	"FORALL" ranges 
		|	
		) 
		(	"WHERE" conjunct 
		|	
		) 
		targetClauses SEMI 
	;


superClasses
	:	simpleTypeLiteral 
		(	COMMA superClasses 
		|	
		) 
	;


simpleTypeLiteral
	:	ID 
	|	FQID 
	|	objectlit 
	;


map_pairs
	:	map_pair ( COMMA map_pair )* 
	;


map_pair
	:	map_value COLON literal 
	;


map_value
	:	literal 
	;


literal
	:	stringlit 
	|	numberlit 
	|	booleanlit 
	|	objectlit 
	|	collectionlit 
	;


tname
	:	ID 
	;


pname
	:	ID 
	;


ranges
	:	range 
		(	objectBody 
		|	
		) 
		( COMMA range 
			(	objectBody 
			|	
			) )* 
	;


conjunct
	:	disjunct ( "AND" disjunct )* 
	;


targetClauses
	:	(	"MAKE" making 
		|	
		) 
		(	"SET" settings 
		|	
		) 
		(	trackingUses 
		|	
		) 
	;


rname
	:	ID 
	;


relatedRules
	:	(	"EXTENDS" 
		|	"OVERRIDES" 
		|	"SUPERSEDES" 
		) 
		related ( COMMA related )* 
	;


making
	:	make ( COMMA make )* 
	;


settings
	:	setting ( COMMA setting )* 
	;


trackingUses
	:	trackingUse ( trackingUse )* 
	;


related
	:	rname 
		(	LBRACK vname ( COMMA vname )* RBRACK 
		|	
		) 
	;


vname
	:	ID 
	|	ANON_ID 
	|	UNDERSCORE 
	;


range
	:	
		(	"EXACT" 
		|	"DYNAMIC" 
		|	
		) 
		typeName context vname 
	;


objectBody
	:	LBRACE ( feature COLON 
			(	LSQUARE featureVals RSQUARE 
			|	featureVal 
			) 
			SEMI )* RBRACE 
	;


typeName
	:	(	DOLLAR factor 
		|	(	UNDERSCORE 
			|	ID 
			|	FQID 
			) 
			
		) 
	;


context
	:	(	AT vname 
		|	
		) 
	;


factor
	:	(	literal 
		|	LBRACK expr RBRACK 
		|	path 
		|	functionCall 
		|	vname 
		) 
	;


objectlit
	:	LANGLE URITOK RANGLE 
	;


disjunct
	:	relation ( "OR" relation )* 
	;


relation
	:	
		(	LBRACK conjunct RBRACK 
		|	range 
			(	objectBody 
			|	
			) 
		|	(	BANG 
			|	"NOT" 
			) 
			relation 
		|	patternUse 
		|	links 
		|	s_ifthenelse 
		|	BOOLEAN 
		|	"UNDEF" factor 
		|	expr 
			(	"BEFORE" expr "IN" path 
			|	(	ASSIGN 
				|	relop 
				) 
				expr 
			) 
		) 
		
	;


s_ifthenelse
	:	"IF" s_ite "ENDIF" 
	;


s_ite
	:	conjunct 
		(	"THEN" conjunct 
		|	
		) 
		(	"ELSEIF" s_ite 
		|	"ELSE" conjunct 
		|	
		) 
		
	;


t_ifthenelse
	:	"IF" t_ite "ENDIF" 
	;


t_ite
	:	conjunct 
		(	"THEN" targetClauses 
		|	
		) 
		(	"ELSEIF" t_ite 
		|	"ELSE" targetClauses 
		|	
		) 
		
	;


patternUse
	:	pname actuals 
	;


links
	:	tname "LINKS" featureMaps 
	;


expr
	:	term 
		(	ADDOP expr 
		|	
		) 
	;


path
	:	(	vname 
		|	objectlit 
		) 
		( (	PERIOD 
			|	ARROW 
			) 
			feature 
			(	actuals 
			|	
			) 
			(	LBRACE RBRACE 
			|	
			) )+ 
	;


relop
	:	RELOP 
	|	LANGLE 
	|	RANGLE 
	;


make
	:	templateUse 
	|	makeObject 
	;


templateUse
	:	patternUse 
	;


makeObject
	:	range 
		(	unique 
		|	
		) 
		(	objectBody 
		|	
		) 
	;


unique
	:	"FROM" uname actuals 
	;


uname
	:	ID 
	;


actuals
	:	LBRACK 
		(	RBRACK 
		|	exprs RBRACK 
		) 
	;


setting
	:	setting_stmt 
	|	BOOLEAN 
	|	t_ifthenelse 
	;


/**
 * Only allow stmts of form Path = Expr or Path() or Path() BEFORE Expr IN Path in clause
 */
setting_stmt
	:	expr 
		(	"BEFORE" expr "IN" path 
		|	ASSIGN expr 
		|	
		) 
		
	;


trackingUse
	:	"LINKING" tname "WITH" featureMaps 
	;


featureMaps
	:	featureMap ( COMMA featureMap )* 
	;


featureMap
	:	fname ASSIGN expr 
	;


fname
	:	ID 
	;


exprs
	:	expr ( COMMA expr )* 
	;


term
	:	factor 
		(	MULOP term 
		|	
		) 
	;


functionCall
	:	fname actuals 
	;


feature
	:	(	ID 
		|	DOLLAR factor 
		) 
	;


vardecl
	:	ID 
	;


enumlit
	:	HASH typeName PERIOD literal 
	;


stringlit
	:	STRING 
	;


numberlit
	:	(	ADDOP 
		|	
		) 
		(	INT 
		|	REAL 
		) 
	;


booleanlit
	:	(	"true" 
		|	"false" 
		) 
	;


collectionlit
	:	LSQUARE exprs RSQUARE 
	;


featureVals
	:	featureVal ( COMMA featureVal )* 
	;


featureVal
	:	(	makeObject 
		|	expr 
		) 
		
	;