/*
 *  ALLL Grammar for ANTLR
 *
 *  (C) 2004 - 2011 Frantisek Zboril jr.
 *  Faculty of Information Technology
 *  Brno University of Technology
 *  zborilf@fit.vutbr.cz
 *  http://www.fit.vutbr.cz/~zborilf
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation. This program 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 General Public License for more details.
 */

grammar ALLL;

@header{
package jTMass.core.jALLL;

import jTMass.TMass;
import jTMass.core.jAMass.TAgent;
import jTMass.core.jALLL.jTObjects.*;
import jTMass.core.jAMass.jActions.*;
}

@lexer::header{
package jTMass.core.jALLL;
}

integer returns [Integer result]
	: NUMBER
	{result= Integer.parseInt($NUMBER.getText());}
	;

apoTau [int level] returns [TRegister register]
	: '\'' {level++;} reg=apoTau[level] {register=reg;} 
	| '&&' {register=new TRegister(level,0);}
        | '&L' {register=new TRegister(level, TConstants._NORegisters+1);}
        | '&N' {register=new TRegister(level, TConstants._NORegisters+2);}
	| '&' regIndex=integer {register=new TRegister(level,regIndex);} 
	;
	
item	returns [TAtom atom]
	:
	 ID  {atom= new TAtom($ID.getText());
	 }
	 | number=integer {atom= new TAtom(number);
	 } 
	 | nAtom=apoTau[0] {atom=nAtom;}
	;
	
item_ap returns [TAtom atom]
	:	
	ID {atom=new TAtom($ID.getText());}
	| number=integer {atom=new TAtom(number);}
	| '_' {atom=new TAtom(TConstants._AnonymousVariable);}
	| nAtom=apoTau[0] {atom=nAtom;}
	;
	
deleteList returns [TList dList]
	: mList=list
	{mList.setType(TConstants._Delete); dList=mList;}
	|'^' '(' dlItem=item_ap 
	{dList=new TList(TConstants._DeletePlan);
	dList.add(dlItem);}
	')'
	;
	
plans returns [TPlan newPlan]
	: 
	{newPlan= new TPlan(TConstants._Plan_Direct_Script);
	TMass._Terminal.printlnDebug("Plan");}
	'<' nAction=action 
	{
	TMass._Terminal.printlnDebug("Action: "+nAction.getContent());
	newPlan.add(nAction);}
	(',' nAction=action
	{
	TMass._Terminal.printlnDebug("Action: "+nAction.getContent());
	newPlan.add(nAction);}
	)* '>'
	{
	TMass._Terminal.printlnDebug("Action: End Of Plan");
	newPlan.add(new TEOP());}
	;
	
addList returns [TList aList]
	: mList=generalList 
	{mList.setType(TConstants._Add); aList=mList;}
	| ('{' 
	{TPlan bPlan=new TPlan(TConstants._StoredPlan);}
	name=item ';' planBody=plans '}'
	{
	bPlan.add(name); bPlan.add(planBody); 
	aList=bPlan;
	}
	)
	;
	
queryListItem returns [TObject result]
	:
	qResultI=item_ap {result=qResultI;}| qResult=queryList {result=qResult;}
	;

queryList returns [TList list]
	:
	{list=new TList(TConstants._QueryList);}
	 '[' mItem=queryListItem 
	 {list.add(mItem);}
	 ( ',' mItem=queryListItem 
	 {list.add(mItem);}
	 ) * ']'
	;
	
generalListItem returns [TObject result]
	: 
	iResult=item {result=iResult;}| gResult=generalList {result=gResult;}
	;	

generalList returns [TList list]
	: 
	{
	TMass._Terminal.printlnDebug("General list: ");
	list=new TList(TConstants._GeneralList);}
	'(' mItem=generalListItem 
	{list.add(mItem);}
	(',' mItem=generalListItem
	{list.add(mItem);} 
	)* ')'
	;
		
list returns [TList result]
	: mResult=queryList {result=mResult;}| mResult=generalList {result=mResult;}
	;

ib_query returns [TReceive reception]
	: sender=item_ap //(',' list )?
	{reception=new TReceive(sender);}
	;

executePlan returns [TPlan ePlan]
	: mPlan=plans {ePlan=mPlan;}
	| 
	'^' '(' name=ID ')'
	{ePlan=new TPlan(TConstants._Plan_Indirect_Call);
	ePlan.addFirst(new TAtom(name.getText()));
	//ePlan=mPlan;
	}	
	;

action returns [TAction action]
	: 
	
	EXECUTE nPlan=executePlan 
	{TMass._Terminal.printlnDebug("Action execute"); action=new TExecute(nPlan);}
	| QUERY nQuery=list
	{TMass._Terminal.printlnDebug("Action query"); action=new TQuery(nQuery);} 
	| ADD nAList=addList
	{TMass._Terminal.printlnDebug("Action add"); action=new TAdd(nAList);} 
	| DELETE nDList=deleteList 
	{TMass._Terminal.printlnDebug("Action delete"); action=new TDelete(nDList);}
	| SEND '(' receiver=item ',' message=generalList ')'
	{TMass._Terminal.printlnDebug("Action send"); action=new TSend(receiver,message);}
	| RECEIVE '(' mAction=ib_query ')' { action=mAction;} 
	| INTERNAL ((regNumber=integer)
	{TMass._Terminal.printlnDebug("Action switch"); action=new TRegisterSwitch(regNumber);}
            |      ('FI')
            {TMass._Terminal.printlnDebug("Action freeze inputs");
            action=new TInternalActions(TInternalActions._IA_FREEZE_INPUTS);}
            |      ('OI')
            {TMass._Terminal.printlnDebug("Action open inputs");
            action=new TInternalActions(TInternalActions._IA_OPEN_INPUTS);}
	);
			
alll	returns [TObject alllObject]
	: gList=generalList {alllObject=gList;} ';' | '^' mPlan=plans {alllObject=mPlan;} ';'
	;

agent_loader [String name, boolean element] returns[TAgent agent]
	:
	{
 	agent=new TAgent(name, element); 
	}
	 
	  INTENTION ':' 
	  nPlan=plans
	  {agent.adoptPlan(nPlan);}
	  ';'
	  
	  (DATABASE ':' 
	  (nList=addList ';'
		{ 
		if(nList.getType()==TConstants._Add)
				agent.addBelief((TList)nList);
		else
			     	agent.addPlan((TPlan)nList, false);}
	  )+)?
	;

ADD 	:	'+';
 
DELETE  :	'-';

EXECUTE :	'@';

QUERY 	:	'#';

SEND	:	'!';

RECEIVE :	'?';	
	
INTERNAL:	'$';

SEMICOLON 
	:	';';
	

NUMBER 	:	(('0')|('1'..'9')('0'..'9')*);

ID	: (('a'..'z'|'A'..'Z'|NUMBER|'_'|'-'|'+'|'.'))+;
	
INTENTION 
	:	'>' 'intention';
					
DATABASE
	:	'>' 'database';

WS
	: (' ' | '\t' | '\r' | '\n' | '\u000C' )+
		{ $channel=HIDDEN;}	
	;		