
/*
 * Copyright (c) 2005, 2006, 2007, 2008 SINTEF
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Jon Oldevik, Tor Neple, Gran Olsen, SINTEF (Norway)- initial API and implementation
 * 
 *    Developed as part of the MODELWARE IP project (http://www.modelware-ist.org/)
 *    Revised as part of the MODELPLEX IP project
 */
 


//grammar MofScript2;



// options{
// output=AST;
//}

@header {
	package org.eclipse.mofscript.parser;	
	import java.util.Vector;
	import java.util.Iterator;
	import org.eclipse.emf.common.util.EList;
	import org.eclipse.mofscript.MOFScriptModel.*;
}

@members{
/*
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
  System.out.println (" ### " + e);
  return e.toString();
}
public String getTokenErrorDisplay(Token t) {
  return t.toString();
}
*/
public void reportError(RecognitionException e) {
  // System.out.println (" reporting error.. " + e);
  MofScriptParseError error = new MofScriptParseError(e, this);
  ParserUtil.getModelChecker().getErrorManager().add(error);  
}

protected void checkVariableDeclarationStatement (MOFScriptStatement statement, MOFScriptStatementOwner owner) {
  if (statement instanceof VariableDeclarationStatement) {
    owner.getVariables().add(((VariableDeclarationStatement)statement).getVariable());
  }
}
}


@lexer::header{
package org.eclipse.mofscript.parser;
import org.eclipse.mofscript.MOFScriptModel.MOFScriptComment;
	}
	
@lexer::members{
public String getErrorMessage(RecognitionException e, String[] tokenNames) {
  // System.out.println (" ### " + e);
  return e.toString();
}

public void reportError(RecognitionException e) {
  // System.out.println (" reporting error.. " + e);
  MofScriptParseError error = new MofScriptParseError(e, this);
  ParserUtil.getModelChecker().getErrorManager().add(error);  
}

}


/**
  *
  * the root of a specification - one or more transformations
  *
  */
  mofscriptSpecification returns [MOFScriptSpecification spec]
  @init{
  	MOFScriptSpecification specification = ParserUtil.getMofScriptModelFactory().createMOFScriptSpecification();  	
	ParserUtil.getModelChecker().setTransformationSpecification(specification);  	          
    Token nextToken = null;
  }
  @after{
      spec=specification;
  }
  : 
  	(tImport=transformationImport
		{
			specification.getImports().add(tImport);
		}
	 )*
    (
    { 
      nextToken=getTokenStream().LT(1);
    }
    (transformation = mofscriptTransformation[specification] {
	ParserUtil.setParseInfo (transformation, nextToken);
	if (transformation != null)
          specification.getTransformation().add(transformation);
    }
    )+
    |
    (
    aspect = mofscriptAspect {
        if (aspect != null)
    	  specification.getTransformation().add(aspect);
    }
    )+
    )
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
	
	/**
	 * Aspects
	 */
	mofscriptAspect returns [MOFScriptAspect theAspect]
	@init{
		MOFScriptAspect aspect = ParserUtil.getMofScriptModelFactory().createMOFScriptAspect();		
	}
        @after {
	    theAspect = aspect;
        }
        : ASPECT name = simpleName 
	CURLY_LEFT
	pointcutOrAdvice[aspect]	
	CURLY_RIGHT
	{
		aspect.setName (name);
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
	
	
	/**
	  * Pointcut or advice
	  *
	  */
	pointcutOrAdvice [MOFScriptAspect ownerAspect]
	:
    ((POINTCUT) => pc=pointcut {ownerAspect.getPointcut().add(pc);} 
	| 
	(BEFORE| AFTER| AROUND)=>ad=advice {ownerAspect.getAdvice().add(ad);} 
	|
	  (variable=variableOrConstantDeclaration 
		   {
		   	  if (variable != null)
		   	  	ownerAspect.getVariables().add(variable);
		   }
	   )
	 |
	  (transformation_rule = transformationRule 
		  	{
		  		if (transformation_rule != null && transformation_rule != null) {
			  		ownerAspect.getTransformationrules().add(transformation_rule);
		  		} else {
		  		}
		  	}
	  )
	)*
	;	
	
		
	/**
	 * pointcut
	 */
	pointcut returns [PointCut thePointCut]
	@init{
		PointCut pointcut = ParserUtil.getMofScriptModelFactory().createPointCut();
		PointCutExpression pcExpression = ParserUtil.getMofScriptModelFactory().createPointCutExpression();
		pointcut.setPointcutexpression (pcExpression);
	} 
        @after {
	        thePointCut = pointcut;
        }
	: POINTCUT name = simpleName (PAREN_LEFT typename=simpleName PAREN_RIGHT {pointcut.setTypeMatch(typename);})? 
	(
		EXECUTE
		{pcExpression.setOperator(PointCutOperator.EXECUTE_LITERAL);}
		|
		CALL
		{pcExpression.setOperator(PointCutOperator.CALL_LITERAL);}
		|
		TARGETPOINTCUT
		{pcExpression.setOperator(PointCutOperator.TARGET_LITERAL);}		
	)
	PAREN_LEFT matchLiteral = stringLiteral PAREN_RIGHT
	(SEMI_COLON)?	
	{
		pointcut.setName (name);		
		pcExpression.setExpressionString(matchLiteral.getValue ());		
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
	
	/**
	  * Advice
	  */
	advice returns [Advice theAdvice]
	@init{
		Advice advice = ParserUtil.getMofScriptModelFactory().createAdvice();
        AdviceOperator operator = null;
	} 
       @after {
	    theAdvice = advice;
       } 
	: (BEFORE {operator=AdviceOperator.BEFORE_LITERAL;}| 
	   AFTER {operator=AdviceOperator.AFTER_LITERAL;}| 
	   AROUND {operator=AdviceOperator.AROUND_LITERAL;}) 
	   pointcutRef=simpleName 
	iteratorBody[advice]
	{
		advice.setName("anonymous");
		advice.setOperator(operator);
		advice.setPointCutRef(pointcutRef);
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	
			


/**.
  * Rules used for temporary parsing of transformation headers / signatures
  */
  mofscriptDeclarationExtra returns [MOFScriptTransformation tmpTransformation]
  @init{
  	MOFScriptSpecification specification = ParserUtil.getMofScriptModelFactory().createMOFScriptSpecification();
  	MOFScriptTransformation transformation = ParserUtil.getMofScriptModelFactory().createMOFScriptTransformation(); 
  	specification.getTransformation().add(tmpTransformation);
  	MOFScriptImport tImport = null;
	ParserUtil.getModelChecker().setTransformationSpecification(specification); 
	// ParserUtil.getModelChecker().setTransformationModel(tmpTransformation);
  }
  @after {
    tmpTransformation = transformation;
  }
  : (transformationImportExtra)* mofscriptTransformationHeader[null, transformation]
  ;



/**
  *
  * Rules to support temporary parsing of imports
  */
transformationImportExtra
	@init{
	}
	: IMPORT (name=simpleName)? importuri=importUri (SEMI_COLON)?
	;
	
	
	/**
	 * Transformation Import 
	 */
transformationImport returns [MOFScriptImport theImport]
	@init{
		MOFScriptImport mttimport = ParserUtil.getMofScriptModelFactory().createMOFScriptImport();		
        Token nextToken = null;
	}
    @after{
       theImport = mttimport;
    }
	: IMPORT (name=simpleName)?     { nextToken=getTokenStream().LT(1);} uri=importUri (SEMI_COLON)?
	{
	    String importuri = uri;
		if (name!= null) mttimport.setName(name);
		mttimport.setImportSemantics(ImportSemantics.IMPORT_LITERAL);
		mttimport.setUri (importuri.substring(1, importuri.length() - 1));
		mttimport.setType (ImportType.LIBRARY_LITERAL);
		ParserUtil.setParseInfo (mttimport, nextToken);
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

importUri returns [String theUri]
	@init{
        String uri = null;
	}
    @after {
        theUri = uri;
    }
	: PAREN_LEFT suri=STRING_LITERAL PAREN_RIGHT {uri = suri.getText();}
	| suri2=STRING_LITERAL {uri = suri2.getText();}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

/**
  *
  * The root of a transformation
  *
  */
mofscriptTransformation [MOFScriptSpecification spec] returns [MOFScriptTransformation theTransformation]
	@init{   
		MOFScriptTransformation transformation = ParserUtil.getMofScriptModelFactory().createMOFScriptTransformation();		
  	    ParserUtil.getModelChecker().setTransformationModel(transformation);		
	}
    @after {
      theTransformation = transformation;
    }
	: mofscriptTransformationHeader [spec, transformation]
	  ((
	    c=CURLY_LEFT	    
	  	mofscriptTransformationBody [spec, transformation]	  
	  	CURLY_RIGHT
        {
          ParserUtil.setParseInfo(transformation, c);
        }
	  )
	  |
	  mofscriptTransformationBody [spec, transformation]
	  )
	  
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
		

/**
  * the header (signature) of a transformation
  */
	mofscriptTransformationHeader [MOFScriptSpecification spec, MOFScriptTransformation transformation]
	@init{
	}
	:  moduleDecl=mofscriptModuleDecl [transformation] 
	   (extendsName=extendsSpecification {transformation.setExtendsName(extendsName);})?
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
/**
  * the body of a transformation
  */
	mofscriptTransformationBody [MOFScriptSpecification spec, MOFScriptTransformation transformation]
	: (tImport=transformationImport
			{
				spec.getImports().add(tImport);
			}
	  )*	   
	  (variable=variableOrConstantDeclaration 
		   {
		   	  if (variable != null)
		   	  	transformation.getVariables().add(variable);
		   }
	   )*
	  (transformation_rule = transformationRule 
		  	{
		  		if (transformation_rule != null && transformation_rule != null) {
			  		transformation.getTransformationrules().add(transformation_rule);
			  		ParserUtil.getModelChecker().checkTransformationRule (transformation_rule, false /* not postCheck*/);
		  		} else {
		  		}
		  	}
	  )*
	  ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
/**
 *
 * Module declaration
 *
 */
mofscriptModuleDecl [MOFScriptTransformation transformationOwner] returns [Vector theParams]
	@init{
       Vector moduleParams = null;
	}
    @after {
      theParams = moduleParams;
    }
	: TEXTTRANSFORMATION moduleName=simpleName PAREN_LEFT mParams=mttModuleParams 
	{
        moduleParams=mParams;
		if (transformationOwner != null) {
		    if (moduleParams != null) {
			for (Iterator it = moduleParams.iterator();it.hasNext();) {
			    MOFScriptParameter param = (MOFScriptParameter)it.next();
			    if (param != null)
				transformationOwner.getParameters ().add(param);
			}
		    }
		   transformationOwner.setName (moduleName);
	       ParserUtil.getModelChecker().checkMetaModels();
		}
	}	
	PAREN_RIGHT (SEMI_COLON)?
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	
/**
 *
 * Parameters to the transformation
 *
 */
mttModuleParams returns [Vector theParams]
	@init{
		Vector params = new Vector ();
	}
    @after {
      theParams = params;
    }
	:	(mttModuleParam COMMA) => param=mttModuleParam COMMA p=mttModuleParams
	{	if (param != null && param != null)
            params.add (param);
        if (p!=null && p != null)
            params.addAll (p);
	}
	| param=mttModuleParam {if (param != null && param != null) params.add(param);}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	

/**
 *
 * A single module parameter
 *
 */
mttModuleParam returns [MOFScriptParameter theParam]
	@init{
		MOFScriptParameter param = null;
		String name = null;
	} 
    @after {
        theParam = param;
    }
	: theIn=IN paramName=simpleName COLON 
	(metaModelName=scopedName{name=metaModelName;}|metamodelLiteral=stringLiteral {name=metamodelLiteral.getValue();})
	{
		param = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
		param.setName (paramName);
		param.setType (name);
		param.setDirection(ParameterDirection.IN_LITERAL);		
		ParserUtil.getModelChecker().addSourceMetaModel (param);				
		ParserUtil.setParseInfo(param, theIn);
	}	
	| theOut=OUT paramName=simpleName COLON 
	(metaModelName=scopedName{name=metaModelName;}|metamodelLiteral=stringLiteral {name=metamodelLiteral.getValue();})
	PAREN_LEFT outModelType=scopedName PAREN_RIGHT
	{
		param = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
		param.setName (paramName);
		param.setType (name);
		param.setDirection(ParameterDirection.OUT_LITERAL);	
        param.setTypePrefix(outModelType);
		ParserUtil.getModelChecker().addTargetMetaModel (param);				
		ParserUtil.setParseInfo(param, theOut);	
		ParserUtil.getExecutionManager().addOutModelTypeMap (paramName, outModelType);		
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		
	
/**
 *
 * Transformation extension
 *
 */
extendsSpecification returns [String theExtendsName]
	@init{ 
        String extendsName = null;
    }
    @after{
        theExtendsName = extendsName;
    }
	: EXTENDS extName=simpleName {extendsName=extName;}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
	
/**
 *
 * Variable or constant declarations
 *
 */
variableOrConstantDeclaration returns [VariableDeclaration theVar]
	@init{
		VariableDeclaration varDecl = null;
	}
    @after {
        theVar = varDecl;
    }
	: decl=variableDeclaration
	{
        varDecl=decl;
  		ParserUtil.getModelChecker().checkVariableDeclaration (varDecl);		
	}
	| decl2=constantDeclaration 
	{
        varDecl=decl2;
  		ParserUtil.getModelChecker().checkVariableDeclaration (varDecl);			
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
/**
 *
 * Variable declaration
 *
 */
variableDeclaration returns [VariableDeclaration theVar]
	@init{
		VariableDeclaration varDecl = ParserUtil.getMofScriptModelFactory().createVariableDeclaration();		
	}
    @after {
        theVar = varDecl;
    }
	: var=VAR varName=simpleName ((COLON)=> COLON varType=type)? 
	    ((EQ)=>EQ (exp=logicalExpression | exp2=createExpression))? (SEMI_COLON)?
	{
		varDecl.setName (varName);
		varDecl.setConstant(false);
        ParserUtil.setParseInfo(varDecl, var);
		if (varType != null) {
			varDecl.setType (varType);
		} else {			
		   varDecl.setType ("String");	
           MofScriptParseError error = new MofScriptParseError ("Property " + varName + " defined without a type. Default type 'String' has been assigned.", 
                                                               var.getLine(), var.getCharPositionInLine(), MofScriptParseError.MOFSCRIPT_WARNING);
		   ParserUtil.getModelChecker().getErrorManager().add(error);
		}
		if (exp != null) {
			varDecl.setValue(exp);
			if (exp instanceof Literal) {
				Literal lit = (Literal)exp;
				LiteralType litType = lit.getType();
				if (litType == LiteralType.INTEGER_LITERAL) {
					varDecl.setType ("Integer");
				} else if (litType == LiteralType.REAL_LITERAL) {
					varDecl.setType ("Real");					
				} else if (litType == LiteralType.BOOLEAN_LITERAL) {
					varDecl.setType ("Boolean");
				}				
			}
			exp = null;
		} else if (exp2 != null) {
		    varDecl.setValue(exp2);
		}
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		
	

/**
 *
 * Constant declaration 
 *
 */
constantDeclaration returns [VariableDeclaration theVar]
	@init{
		VariableDeclaration varDecl = ParserUtil.getMofScriptModelFactory().createVariableDeclaration();		
	}	
    @after {
        theVar = varDecl;
    }
	: prop=PROPERTY varName=simpleName ((COLON)=>COLON cType=type)? EQ exp=logicalExpression (SEMI_COLON)?
	{
		varDecl.setName (varName);
		varDecl.setConstant(true);
		varDecl.setValue(exp);
            //		varDecl.setCalculatedValue(null);
        ParserUtil.setParseInfo(varDecl, prop);
		if (cType != null) {
			varDecl.setType (cType);
		} else {
		   varDecl.setType ("String");		
           MofScriptParseError error = new MofScriptParseError ("Property " + varName + " defined without a type. Default type 'String' has been assigned.", 
                                                               prop.getLine(), prop.getCharPositionInLine(), MofScriptParseError.MOFSCRIPT_WARNING);
		   ParserUtil.getModelChecker().getErrorManager().add(error);
        }
		exp = null;
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	
	
/**
 *
 * Legal types
 *
 */
typeName returns [String typeName]
    @init{
        String tName = null;
    }
    @after{
        typeName = tName;
    }
	: STRING {tName="String";}
	| BOOLEAN {tName="Boolean";}
	| INTEGER {tName="Integer";}
	| REAL {tName="Real";}
	| HASHTABLE {tName="Hashtable";}
	| DICTIONARY{tName="Dictionary";}	
	| LIST{tName="List";}
	| OBJECT {tName="Object";}
	;
	catch [RecognitionException rtex] {
		String msg = "Unknown type name:";
		int index = msg.indexOf(':');			
		String token = "";
		if (index > -1)
			token = msg.substring(index +1 , msg.length()).trim();
		if (token.equalsIgnoreCase("String"))
			msg += " (try String)";
		else if (token.equalsIgnoreCase ("Integer"))
			msg += " (try Integer)";		
		else if (token.equalsIgnoreCase ("Boolean"))
			msg += " (try Boolean)";		
		else if (token.equalsIgnoreCase ("Real"))
			msg += " (try Real)";		
		else if (token.equalsIgnoreCase ("Hashtable"))
			msg += " (try Hashtable)";		
		else if (token.equalsIgnoreCase ("Dictionary"))
			msg += " (try Dictionary)";				
		else if (token.equalsIgnoreCase ("List"))		
			msg += " (try List)";		
		else if (token.equalsIgnoreCase ("Object"))
			msg += " (try Object)";
		else 
		    msg += " (try one of String, Integer, Boolean, Real, Hashtable/Dictionary, List, Object)";
		MofScriptParseError error = new MofScriptParseError (msg, rtex.line, rtex.charPositionInLine);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
    }
	
	
	
/**
 *
 * Transformation rule
 *
 */		
transformationRule returns [TransformationRule theRule]
	: rule1=normalTransformationRule 	
	{
        TransformationRule r = rule1;
        theRule=r;
		if (r != null && r.getContext() == null) {   
			MOFScriptParameter context = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
			context.setType("module");
			context.setName("self");
			r.setContext(context);
		}		
	}
	| rule2=abstractTransformationRule {theRule=rule2;}
	;

/**
 *
 * An abstract transformation rule 
 *
 */
abstractTransformationRule returns [TransformationRule theRule]
	@init{
		TransformationRule rule = ParserUtil.getMofScriptModelFactory().createTransformationRule();		
	    rule.setReturn (null);	    
	}
    @after {
        theRule = rule;
    }
	:
	ABSTRACT contextType=context name=simpleName params=parameters
	 {
			if (contextType != null) {
			    MOFScriptParameter context = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
			    context.setType(contextType);
			    context.setName("self");
			    rule.setContext(context);
			}	 	
		  	rule.setIsAbstract (true);	 	
		  	rule.setIsEntryPoint (false);
		  	rule.setName(name);
			rule.setLine(ParserUtil.getLine());
			rule.setColumn (ParserUtil.getColumn());
        if (params != null && params != null) {
          for (Iterator it = params.iterator();it.hasNext();) {
		 	  MOFScriptParameter p = (MOFScriptParameter) it.next();
			  rule.getParameters().add(p);
		  }
        }	 	
	 }
	 (COLON return_type=returnType
		{
		rule.setReturn (return_type);		
		}
	 )?	
	 (SEMI_COLON)?
	 ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
		rule = null;
	} 	 

/**
 *
 * A normal transformation rule
 *
 */
normalTransformationRule returns [TransformationRule theRule]
	@init{ 
        TransformationRule rule = ParserUtil.getMofScriptModelFactory().createTransformationRule();
	  rule.setReturn (null);
	}
    @after {
        theRule = rule;
    }
	: (contextType=context 
		{
			
			if (contextType != null) {   
			    MOFScriptParameter contextParam = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
			    contextParam.setType(contextType);
			    contextParam.setName("self");
			    rule.setContext(contextParam);
                contextParam.setLine(ParserUtil.getLine());
                contextParam.setColumn(ParserUtil.getColumn());
			}		
		}		
	  )?
	 (
	 	entry=MAIN PAREN_LEFT PAREN_RIGHT 
	 	{
		  	rule.setIsEntryPoint (true);
		  	rule.setIsAbstract (false);
		  	rule.setName(entry.getText());
			rule.setLine(ParserUtil.getLine());
			rule.setColumn (ParserUtil.getColumn());		  	
	 	}
	 |  name=simpleName params=parameters 
	 {
		  	rule.setIsEntryPoint (false);
		  	rule.setName(name);	 	
			rule.setLine(ParserUtil.getLine());
			rule.setColumn (ParserUtil.getColumn());
        if (params != null && params != null) {
		  for (Iterator it = params.iterator();it.hasNext();) {
			MOFScriptParameter p = (MOFScriptParameter) it.next();
			rule.getParameters().add(p);
	  	  }	 	
        }
	 }
	 )
	 (COLON return_type=returnType
		{
		rule.setReturn (return_type);		
		}
	 )?
	CURLY_LEFT
	(transformationRuleBody [rule])
	CURLY_RIGHT	 
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
		rule = null;
	} 		

/**
 *
 * The context of a rule
 *
 */
context returns [String theName]
	@init{
		String cName = null;
	}
    @after {
        theName = cName;
    }
	:	(simpleName DOT simpleName)=>sn=scopedName COLONCOLON
	{
		cName = sn;
	}
	|
        (simpleName DOT typeName) => contextName=scopedExistingType COLONCOLON
	{
		cName = contextName;
	}
	| (MODULE) => MODULE COLONCOLON
	{
		cName = "module";
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

scopedExistingType returns [String theType]
	@init{
        String type = null;
	}
    @after {theType = type;}
	: mmRef = simpleName DOT tn=typeName
	{
		type = mmRef + "." + tn;
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	
	
		
/**
 *
 * The body of a rule
 *
 */
transformationRuleBody [MOFScriptStatementOwner owner]
	@init{
		MOFScriptStatement statement = null;
		boolean protectedSection = false;
	}
	: 
	(
       (standardTransformationRuleStatements[owner] |
        unprotectedTransformationRuleStatements[owner])
	)*
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	
/**
 *
 * Unprotected rule statements
 *
 */
standardTransformationRuleStatements [MOFScriptStatementOwner owner]
		@init{
		MOFScriptStatement statement = null;
		StatementBlock b = ParserUtil.getMofScriptModelFactory().createStatementBlock();
		b.setProtected(true);		
		}
		: transformationRuleStatements [owner, b]
		{
		   	owner.getBlocks().add(b);			
		}
        ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	

/**
 *
 * protceted rule statements 
 *
 */
unprotectedTransformationRuleStatements [MOFScriptStatementOwner owner]
	 @init {
			StatementBlock b = ParserUtil.getMofScriptModelFactory().createStatementBlock();
			b.setProtected(false);
	   }
	   : UNPROTECT (PAREN_LEFT reference=simpleName PAREN_RIGHT)? CURLY_LEFT
	   (transformationRuleStatements [owner, b])*
	   {
	   	if (reference !=  null)
		   	b.setReference (reference);
	   	owner.getBlocks().add(b);
	   }
	   CURLY_RIGHT
	   ; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
	
/**
 *
 * Statements
 *
 */

transformationRuleStatements [MOFScriptStatementOwner owner, StatementBlock statementBlock]
		@init{
		Vector expList = null;
		}			   
    : 
    (((simpleName|STDOUT) DOT (PRINT|PRINTLN))|
     (PRINT|PRINTLN) |
     (anyKindOfSimpleExpression ARROW) |
     (scopedName (EQ|PLUS EQ)) |
     (scopedName PAREN_LEFT) |
     (RESULT) |
     (FILE)|
     (NEWLINE|SPACE|TAB|INDENT|UNDENT|LOG)|
     (IF) | 
     (BREAK)|
     (WHILE)|
     (RETURN)|
     (VAR)|
     (PROPERTY)
     ) =>
     statement = singleStatement
	   {
	   	if (statement != null && statement != null){
			owner.getStatements().add(statement);
			statementBlock.getStatements().add(statement);
            checkVariableDeclarationStatement(statement, owner);
	   	}
	   } 
      |(simpleExpression | stringLiteral)=> composedExpressionList[owner, statementBlock]
	   ; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}   	
		
/**
 *
 * If statements
 *
 */	
ifStatement  returns [IfStatement theStatement]
	@init{
		IfStatement statement = ParserUtil.getMofScriptModelFactory().createIfStatement();
        IfStatement elseBranch = null;
	}
    @after {theStatement = statement;}
	: IF PAREN_LEFT exp=logicalExpression p=PAREN_RIGHT iteratorBody [statement] {
		statement.setIfExpression (exp);
	} 
	((ELSE IF PAREN_LEFT)=> ELSE IF PAREN_LEFT exp=logicalExpression PAREN_RIGHT 
	{elseBranch = ParserUtil.getMofScriptModelFactory().createIfStatement();}
	iteratorBody [elseBranch] {
		elseBranch.setIfExpression (exp);
 	  	statement.getElseBranch().add(elseBranch);		
	})*	
	((ELSE (iteratorBody[null]))=> ELSE {elseBranch = ParserUtil.getMofScriptModelFactory().createIfStatement();} iteratorBody [elseBranch]
 	  {
 	  	statement.getElseBranch().add(elseBranch);
	  }
	)?
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}		

/**
 *
 * While statement (while)
 *
 */
 whileStatement returns [WhileStatement theStatement]
	@init{
		WhileStatement statement = ParserUtil.getMofScriptModelFactory().createWhileStatement();
		String itVar = null, t = null;
		int line = 0;		
		
	}
    @after {theStatement=statement;}
	: WHILE PAREN_LEFT (condition=logicalExpression)? p=PAREN_RIGHT 
	{
	} 
	
	iteratorBody [statement] 
	{
		statement.setCondition(condition);
	} 
	
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
 
/**
 *
 * Iterator statement (FOREACH)
 *
 */
iteratorStatement [SimpleExpression source] returns [IteratorStatement theStatement]
	@init{
		IteratorStatement statement = ParserUtil.getMofScriptModelFactory().createIteratorStatement();
		SimpleExpression sourceReference = source;
		int line = 0;
	}
    @after {theStatement = statement;}
	: ARROW FOREACH PAREN_LEFT itVar=simpleName (COLON t=type)? (PIPE filter=filterSpec)? PAREN_RIGHT 
	(BETWEEN PAREN_LEFT betweenExpression=valueExpression (PIPE filter=filterSpec)? PAREN_RIGHT{if (betweenExpression != null)statement.setBetween(betweenExpression);})?	
	iteratorBody[statement]
	{
		if (t != null){
			statement.setType (t);
			// System.out.println ("TYPE: " + t);
		}
		statement.setVariable (itVar);
		statement.setSource (sourceReference);
		if (filter != null) {
			statement.setFilterExpression (filter);
		}
		
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error);
        recover(input, rtex);
	}		

/**
 *
 * Filter for an iterator
 *
 */
filterSpec returns [Expression theFilter]
	@init{
		Expression filter = null;
	}
    @after {theFilter = filter;}
	: 
		(lexp=logicalExpression
		{
		// System.out.println ("filter : [" + filter.getNameRef() + "]");
		})
	{
        filter = lexp; 
		if (filter == null) {
			System.out.println ("Empty filter");
		}
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 






logicalExpression returns [Expression theExp]
    :
   andExp=andExpression 
   {
       theExp=andExp;
   }
  ;


andExpression returns [Expression theExp]
   : (orExpression AND) => orExp=orExpression andExp=andExpressionPart
   {
       andExp.setPart1(orExp);
       theExp = andExp;
   }  
   | orExp=orExpression
   {
       theExp = orExp;
   }
   ;

andExpressionPart returns [LogicalExpression theExp]
   : AND exp=andExpression
   {
       LogicalExpression logicalExpr = ParserUtil.getMofScriptModelFactory().createLogicalExpression();		
       logicalExpr.setOperator(LogicalOperator.AND_LITERAL);
       logicalExpr.setPart2(exp); 
       theExp = logicalExpr;
   }
   ;

orExpression returns [Expression theExp]
   : (comparisonExpression OR) => cexp=comparisonExpression part=orExpressionPart  
    {
        part.setPart1(cexp);
	    theExp = part;
    }
   | cexp=comparisonExpression
   {
       theExp = cexp;
   }
   ;

orExpressionPart returns [LogicalExpression theExp]
   : OR exp=orExpression
   {
       LogicalExpression logicalExpr = ParserUtil.getMofScriptModelFactory().createLogicalExpression(); 
       logicalExpr.setOperator(LogicalOperator.OR_LITERAL);
       logicalExpr.setPart2(exp); 
       theExp = logicalExpr;      
   }
   ;


/**
 * 
 * NOT
 *
 */
notExpression returns [LogicalExpression theExp]
	@init{
		LogicalExpression logicalExpr = null; 
//		Expression exp2 = null;		
	}
    @after {theExp = logicalExpr;}
	: NOT exp1=andExpression
	{
		logicalExpr = ParserUtil.getMofScriptModelFactory().createLogicalExpression();		
		logicalExpr.setOperator(LogicalOperator.NOT_LITERAL);
		logicalExpr.setPart1(exp1);
	}
	;

comparisonExpression returns [Expression theExp]
   options{k=1;}
   : (valueExpression comparisonOperator)=> vexp=valueExpression cexp=comparisonExpressionPart
   {
       cexp.setPart1((SimpleExpression)vexp);
       theExp = cexp;       
   } 
   | (valueExpression)=>vExp=valueExpression
   {
       theExp = vExp;
   }
   | uExp=unaryExpression
   {
       theExp=uExp;
   }
//   : unaryExpression  (comparisonOperator unaryExpression)*
// |stringLiteralSimpleExpression op=comparisonOperator exp2=valueExpression
   ;



comparisonExpressionPart returns [ComparisonExpression theExp]
   : op=comparisonOperator unExp=valueExpression
   {
       ComparisonExpression comparisonExp = ParserUtil.getMofScriptModelFactory().createComparisonExpression();		
       comparisonExp.setPart2(unExp);
       comparisonExp.setOperator(op);
       theExp = comparisonExp; 
       ParserUtil.setParseInfo(comparisonExp, unExp);

   }
   ;

arithmeticExpression returns [ArithmeticExpression theExp]
    :sexp=anyKindOfSimpleExpression part2=arithmeticExpressionPart0
{
    
    part2.setPart1(sexp);
    theExp = part2;
}
;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

// "per" + test() + "ole"
arithmeticExpressionPart0 returns [ArithmeticExpression theExp]
   options{greedy=false;}
:
    (arithmeticOperator anyKindOfSimpleExpression)=>aexp1=arithmeticExpressionPart1 
{
    theExp = aexp1;
}
|   (arithmeticOperator PAREN_LEFT)=> aexp2=arithmeticExpressionPart2
{
    theExp = aexp2;
}

    ;


arithmeticExpressionPart1 returns[ArithmeticExpression theExp]
//    options{greedy=false;}
    : (arithmeticOperator anyKindOfSimpleExpression arithmeticOperator)=>
      op=arithmeticOperator sexp=anyKindOfSimpleExpression part2=arithmeticExpressionPart0
{
    ArithmeticExpression aexp = ParserUtil.getMofScriptModelFactory().createArithmeticExpression ();    
    aexp.setOperator(op);
    part2.setPart1(sexp);
    aexp.setPart2(part2);	        
    theExp=aexp;
    ParserUtil.setParseInfo(aexp, sexp);
}
    | (arithmeticOperator anyKindOfSimpleExpression) => op=arithmeticOperator sexp=anyKindOfSimpleExpression 
{
    ArithmeticExpression aexp = ParserUtil.getMofScriptModelFactory().createArithmeticExpression ();
    aexp.setPart2(sexp);
    aexp.setOperator(op);
    theExp=aexp;
    ParserUtil.setParseInfo(aexp, sexp);
}
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

arithmeticExpressionPart2 returns[ArithmeticExpression theExp]
    : (arithmeticExpressionPart3 arithmeticOperator)=> part1=arithmeticExpressionPart3 part2=arithmeticExpressionPart0
{
    
    part2.setPart1(part1.getPart2());
    part1.setPart2(part2);
    theExp = part1;
}
    | aexp=arithmeticExpressionPart3
{
    theExp = aexp;
}	
    ;

arithmeticExpressionPart3 returns [ArithmeticExpression theExp]
    : op=arithmeticOperator PAREN_LEFT aexp=arithmeticExpression PAREN_RIGHT 
    {
	ArithmeticExpression aexp2 = ParserUtil.getMofScriptModelFactory().createArithmeticExpression ();    
	aexp2.setOperator(op);
	aexp2.setPart2(aexp);
	theExp = aexp2;
    ParserUtil.setParseInfo(aexp2, aexp);
    }
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}


arithmeticOperator returns[ArithmeticOperator theOp]
    : PLUS {theOp=ArithmeticOperator.PLUS_LITERAL;}
   | MINUS {theOp=ArithmeticOperator.MINUS_LITERAL;}
   | STAR {theOp=ArithmeticOperator.MULT_LITERAL;}
   | DIV {theOp=ArithmeticOperator.DIV_LITERAL;}
   ;



unaryExpression returns [Expression theExp]
   :nexp=notExpression 
   {
       theExp=nexp;
   }
   | PAREN_LEFT aexp=andExpression PAREN_RIGHT
   {
       theExp=aexp;
   }
   ;

		

/**
 *
 * Comparison Operator (= != < > <= >=)
 *
 */
comparisonOperator returns [ComparisonOperator theOp]
	@init{
		ComparisonOperator op = ComparisonOperator.EQ_LITERAL;
	}
    @after {theOp = op;}
	: EQ {op = ComparisonOperator.EQ_LITERAL;}
	| DOUBLE_EQ {op = ComparisonOperator.EQ_LITERAL;}
	| NE {op = ComparisonOperator.NE_LITERAL;}
	| LT {op = ComparisonOperator.LT_LITERAL;}
	| GT {op = ComparisonOperator.GT_LITERAL;}
	| LE {op = ComparisonOperator.LE_LITERAL;}
	| GE {op = ComparisonOperator.GE_LITERAL;}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
	


/**
 *
 * The body of an iterator
 *
 */
iteratorBody [MOFScriptStatementOwner statementOwner]
    @init{
		StatementBlock b = ParserUtil.getMofScriptModelFactory().createStatementBlock();
		b.setProtected(true);
    }
    :scopedStatement [statementOwner]
    | transformationRuleStatements[statementOwner, b]    
    {
       statementOwner.getBlocks().add(b);
    }
/*
	| statement=singleStatement
	{
		if (statement != null && statement != null)
			statementOwner.getStatements().add(statement);
	}
*/
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		

/**
 *
 * Scoped statement - a statement within curly brackets
 *
 */
scopedStatement [MOFScriptStatementOwner owner]
	@init{
	 }
	: CURLY_LEFT transformationRuleBody [owner] CURLY_RIGHT
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	
	
/**
 *
 * Single statement
 *
 */
singleStatement  returns [MOFScriptStatement theStatement] 
    options{
     k=1;
    }
	@init{
        MOFScriptStatement retStat = null;
		Vector expList = null; 
	}
    @after {theStatement = retStat;}	
    : 
    (((simpleName|STDOUT) DOT (PRINT|PRINTLN))|(PRINT|PRINTLN))=> pst = printStatement[null] {retStat=pst;}
    | (anyKindOfSimpleExpression ARROW) => iteratorExpression=anyKindOfSimpleExpression itStat=iteratorStatement[iteratorExpression] {retStat=itStat;}
	| (scopedName (EQ | PLUS EQ))=>sName=scopedName gast=generalAssignment [sName]   {retStat = gast;}
	| (scopedName PAREN_LEFT)=> sName=scopedName fcst=functionCallStatement[sName]  {retStat = fcst;}
	| rest = resultAssignment	 {retStat = rest;}
	| filest = fileStatement  {retStat = filest;}
	| dpst = directPrintStatement  {retStat = dpst;}
	| ifst = ifStatement  {retStat = ifst;}
	| bst = breakStatement  {retStat = bst;}
	| wst = whileStatement {retStat = wst;}
    | ret = returnStatement {retStat = ret;}
    | variable=variableOrConstantDeclaration 
      {
       retStat = ParserUtil.getMofScriptModelFactory().createVariableDeclarationStatement();
       ((VariableDeclarationStatement)retStat).setVariable(variable);
      }       
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error);
        recover(input, rtex);
	}
	
/**
 *
 * Result assignment statement
 *
 */
resultAssignment returns [ResultAssignment theStatement]
	@init{	
        ResultAssignment statement = ParserUtil.getMofScriptModelFactory().createResultAssignment();
	}
    @after {theStatement = statement;}
	: result=RESULT (DOT n=scopedName)? operator=assignmentPart exp=valueExpression (SEMI_COLON)?
	{
        if (n != null) {
		   statement.setResultPart(n);
        }
		statement.setOperator (operator);
		statement.setExpression (exp);
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	


/**
 *
 * Return statement
 *
 */
 returnStatement returns [ReturnStatement theStatement]
     @init {
        ReturnStatement statement = ParserUtil.getMofScriptModelFactory().createReturnStatement();
     }
     @after {theStatement = statement;}
     : (RETURN logicalExpression)=> RETURN vexp=logicalExpression (SEMI_COLON)?
     {
	 statement.setExpression(vexp);
     }
     | RETURN (SEMI_COLON)?
     {
	 statement.setExpression(null);
     }
     ;
	
/**
 *
 * Assignment part
 *
 */
assignmentPart returns [AssignmentOperator theOp]
	@init{AssignmentOperator operator = null;}
    @after {theOp = operator;}
	: PLUS EQ {operator = AssignmentOperator.PLUS_EQ_LITERAL;}	
	| EQ {operator = AssignmentOperator.EQ_LITERAL;}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
	

/**	
 *
 * Normal assignment (to variables)
 *
 */
generalAssignment [String sName] returns [GeneralAssignment theStatement]
	@init{		
		GeneralAssignment statement = ParserUtil.getMofScriptModelFactory().createGeneralAssignment ();
	}
    @after {theStatement = statement;}
	:	operator=assignmentPart (exp=valueExpression {statement.setExpression(exp);}| exp2=createExpression {statement.setExpression(exp2);}) (SEMI_COLON)?
	{
		statement.setName(sName);
		statement.setOperator (operator);
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
/**
 *
 * File statement
 *
 */
fileStatement returns [FileStatement theStatement]
	@init{
		FileStatement statement = ParserUtil.getMofScriptModelFactory().createFileStatement ();
	}
    @after {theStatement = statement;}
	:  FILE (nameRef = simpleName)?
	  PAREN_LEFT exp=valueExpression PAREN_RIGHT (SEMI_COLON)?
	{
		statement.setFileURI(exp);
		if (nameRef != null)
		   statement.setFileReference (nameRef);
        ParserUtil.setParseInfo(statement, exp);
	}
 	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}  	

/**
 *
 * Print statement
 *
 */
printStatement [String context] returns [PrintStatement theStatement]
	@init{
		PrintStatement statement = ParserUtil.getMofScriptModelFactory().createPrintStatement ();
		String print = "println";
	}
    @after {theStatement = statement;}
	// : (context:STDOUT DOT)? printCmd:PRINT PAREN_LEFT printExp=expression PAREN_RIGHT
	 // : ((context:SIMPLE_NAME DOT)? (printCmd:PRINT PAREN_LEFT printExp=expression PAREN_RIGHT))
	 : 
	 ((STDOUT) => stdout=STDOUT DOT | theContext=simpleName DOT{context=theContext;})? (PRINT {print="print";}|PRINTLN) paren=PAREN_LEFT 
	 	printExp=valueExpression p=PAREN_RIGHT (SEMI_COLON)?
	{
		statement.setContext("");		
		if (stdout != null)
			context = stdout.getText();
		if (context != null)
			statement.setContext(context);
		statement.setPrintCommand (print);
		statement.setPrintBody(printExp);
        ParserUtil.setParseInfo(statement, paren);

	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
/**
 *
 * Function Call statement
 *
 */
functionCallStatement [String sName] returns [FunctionCallStatement theStatement]
	@init {
		FunctionCall fCall = ParserUtil.getMofScriptModelFactory().createFunctionCall();
		String functionName = sName;
		FunctionCallStatement statement = ParserUtil.getMofScriptModelFactory().createFunctionCallStatement (); 
	 }
    @after {theStatement = statement;}
	: pl=PAREN_LEFT {ParserUtil.setParseInfo (fCall, pl);} actualParameters[fCall] p=PAREN_RIGHT (SEMI_COLON)?
	{
		if (functionName.toLowerCase().startsWith ("super.")) {
			fCall.setName (functionName.substring(6));
			fCall.setIsSuperCall (true);
		} else {
			fCall.setName (functionName);
			fCall.setIsSuperCall (false);
		}				
//		System.out.println ("Found FunctionCallStatement: " + fCall.getName());		
		statement.setFunction(fCall);
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);		
    }



/**
  *
  */	
composedExpressionList [MOFScriptStatementOwner owner, StatementBlock statementBlock]
    options{greedy=false;}
	@init{
		ValueExpression valExp = null;
		SimpleExpression iteratorContext = null;
		Vector followingStatements = new Vector ();		
        Vector expList = null;
	}
	    :eList = expressionList [followingStatements]
		{		
            expList = eList;
			if (expList.size() > 0) {
				valExp = (ValueExpression)expList.get(0);
				if (valExp instanceof FunctionCall) {
					FunctionCallStatement fStatement = ParserUtil.getMofScriptModelFactory().createFunctionCallStatement ();
					fStatement.setFunction ((FunctionCall)valExp);
					owner.getStatements().add(fStatement);
					if (statementBlock != null) statementBlock.getStatements().add(fStatement);
				} else if (valExp instanceof ArithmeticExpression){
					while (valExp instanceof ArithmeticExpression) {
						ArithmeticExpression aexp = (ArithmeticExpression)valExp;
						valExp = aexp.getPart2();
						if (aexp.getPart2() instanceof FunctionCall || aexp.getPart1() instanceof FunctionCall) {
							PrintStatement printstatement = null;
							printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
							// statement.setPrintCommand ("print");
							printstatement.setPrintBody(aexp.getPart1());
							owner.getStatements().add(printstatement);
							if (statementBlock != null) statementBlock.getStatements().add(printstatement);							
							if (!(valExp instanceof ArithmeticExpression)) {
									printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
									// statement.setPrintCommand ("print");
									printstatement.setPrintBody(valExp);
									owner.getStatements().add(printstatement);
									if (statementBlock != null) statementBlock.getStatements().add(printstatement);									
							}
						} else if (aexp.getPart2() instanceof ArithmeticExpression) {
							PrintStatement printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
							// statement.setPrintCommand ("print");
							printstatement.setPrintBody(aexp.getPart1());
							owner.getStatements().add(printstatement);
							if (statementBlock != null) statementBlock.getStatements().add(printstatement);
						} else {
							PrintStatement printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
							// statement.setPrintCommand ("print");
							printstatement.setPrintBody(aexp);
							owner.getStatements().add(printstatement);													
							if (statementBlock != null) statementBlock.getStatements().add(printstatement);
						}
					}
				} else {
						PrintStatement printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
						// statement.setPrintCommand ("print");
						printstatement.setPrintBody(valExp);
						owner.getStatements().add(printstatement);
						if (statementBlock != null) statementBlock.getStatements().add(printstatement);
				}
			}
			if (followingStatements.size() > 0) {
				MOFScriptStatement statement = null;
				for (Iterator it = followingStatements.iterator(); it.hasNext();) {
					statement = (MOFScriptStatement) it.next();
					owner.getStatements().add(statement);
					if (statementBlock != null) statementBlock.getStatements().add(statement);
                    checkVariableDeclarationStatement(statement, owner);
				}
			}
		}		
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		
		
/**
 *
 * List of expressions treated as output printing expressions
 *
 */
expressionList [Vector followingStatements] returns [Vector expressions] 
	@init{
        Vector expList = new Vector ();
	}
    @after {expressions = expList;}
	: nslList = nonStringLiteralExpressionList [followingStatements]
	{
		expList.add(nslList);			
	}
	| slList = stringLiteralExpressionList [followingStatements]
	{
		expList.add(slList);			
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	
		
	

nonStringLiteralExpressionList [Vector followingStatements] returns [ValueExpression theExp]
   options{k=1;}
   @init{
    ValueExpression valueExp = null;
   }
    @after {theExp = valueExp;}
   : (simpleExpression (stringLiteral | PLUS)) => exp1=simpleExpression exp2=nonStringLiteralExpressionPart[followingStatements]
   {
		ArithmeticExpression cexp = ParserUtil.getMofScriptModelFactory().createArithmeticExpression();
		cexp.setOperator(ArithmeticOperator.PLUS_LITERAL);
		cexp.setPart1(exp1);
		cexp.setPart2(exp2);		
		valueExp = cexp;
        ParserUtil.setParseInfo(valueExp, exp1);
   }
   | exp=simpleExpression (SEMI_COLON)?
   {
        valueExp = exp;
        ParserUtil.setParseInfo(valueExp, exp);   
   }
   ;

nonStringLiteralExpressionPart [Vector followingStatements] returns [ValueExpression theExp]
    @init{
    ValueExpression valueExp = null;
    }
@after {theExp = valueExp;}
   : (stringLiteral)=> slList=stringLiteralExpressionList[followingStatements]
   {
       valueExp=slList;
       ParserUtil.setParseInfo(valueExp, slList);
   }
   | (PLUS stringLiteral)=> PLUS slList=stringLiteralExpressionList[followingStatements]
   {
       valueExp=slList;
       ParserUtil.setParseInfo(valueExp, slList);
   }
   | (PLUS simpleExpression) => PLUS newnslList=nonStringLiteralExpressionList[followingStatements]   
   {
     valueExp = newnslList;
     ParserUtil.setParseInfo(valueExp, newnslList);
   }
   | PLUS nslList=nonStringLiteralExpressionPart[followingStatements]
   {
       valueExp=nslList;
       ParserUtil.setParseInfo(valueExp, nslList);
   }
   ;


	
stringLiteralExpressionList [Vector followingStatements] returns [ValueExpression theExp] 
   options{
    k=1;
   }
	@init{
		ValueExpression valueExp = null;
	}
    @after {theExp = valueExp;}
    : (stringLiteralSimpleExpression (((simpleName|STDOUT) DOT (PRINT|PRINTLN))|
     (PRINT|PRINTLN) |
     (anyKindOfSimpleExpression ARROW) |
     (scopedName (EQ|PLUS EQ)) |
     (scopedName PAREN_LEFT) |
     (RESULT) |
     (FILE)|
     (NEWLINE|SPACE|TAB|INDENT|UNDENT|LOG)|
     (IF) | 
     (BREAK)|
     (WHILE)|
     (RETURN)|
     (VAR)|(PROPERTY)				      
     )) =>
     exp=stringLiteralSimpleExpression statement = singleStatement
     {
       valueExp = exp;
       ParserUtil.setParseInfo(valueExp, exp);
       followingStatements.add(statement);
     }
/*
    : (stringLiteralSimpleExpression anyKindOfSimpleExpression ARROW)=> exp=stringLiteralSimpleExpression itExp=anyKindOfSimpleExpression itSt=iteratorStatement[itExp]
    {
        valueExp=exp;
        followingStatements.add(itSt);
    }
*/
    | (stringLiteral (simpleExpression|PLUS)) => exp1=stringLiteralSimpleExpression exp2=stringLiteralExpressionPart[followingStatements]   
    {
	if (exp2 != null) {
		ArithmeticExpression cexp = ParserUtil.getMofScriptModelFactory().createArithmeticExpression();
		cexp.setOperator(ArithmeticOperator.PLUS_LITERAL);
		cexp.setPart1(exp1);
		cexp.setPart2(exp2);		
		valueExp = cexp;
        ParserUtil.setParseInfo(valueExp, exp1);
	}
	else {
	    valueExp = exp1;
        ParserUtil.setParseInfo(valueExp, exp1);
    }
    }
    | exp=stringLiteralSimpleExpression (SEMI_COLON)?
    {
      valueExp = exp;
      ParserUtil.setParseInfo(valueExp, exp);
    }

    ;
    

stringLiteralExpressionPart [Vector followingStatements] returns [ValueExpression theExp]
    options{
      k=1;
    }
    @init {
     ValueExpression valueExp = null;
    }
    @after {theExp = valueExp;}
    :(simpleExpression) => nslList=nonStringLiteralExpressionList[followingStatements]
    {
	valueExp=nslList;
    ParserUtil.setParseInfo(valueExp, nslList);
    }
    | PLUS (nslList=nonStringLiteralExpressionList[followingStatements]{valueExp=nslList;} | slList=stringLiteralExpressionList[followingStatements]{valueExp=slList;})
    |(simpleExpression EQ) => sSt=singleStatement
    {
	if (sSt != null && sSt != null)
    	   followingStatements.add(sSt);
    }
    ;
    
		
		
/**
  * Break statement breaks from loops
  *
  */
  
breakStatement returns [BreakStatement theStatement]
	@init{
		BreakStatement breakSt = ParserUtil.getMofScriptModelFactory().createBreakStatement ();	
	}
    @after {theStatement = breakSt;}
	: b=BREAK (SEMI_COLON)?
    {
     ParserUtil.setParseInfo(breakSt, b);
    }     		
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

/**
 *
 * Some direct print commands (newline, indent, log..)
 *
 */
directPrintStatement returns [PrintStatement theStatement]
	@init{
		PrintStatement printstatement =  ParserUtil.getMofScriptModelFactory().createPrintStatement ();		
		printstatement.setContext("");
        Token nextToken = null;
	}	
    @after {theStatement = printstatement;}    
	: dpc=directPrintCommand (SEMI_COLON)?
	{
        nextToken=getTokenStream().LT(-1);
        ParserUtil.setParseInfo(printstatement, nextToken);
        String s = dpc;
		if (s.equalsIgnoreCase ("indent") || s.equalsIgnoreCase("undent")) {
			printstatement.setPrintCommand (s);
		} else {	
			printstatement.setPrintCommand("print");		
			Literal lit = ParserUtil.getMofScriptModelFactory().createLiteral();
			lit.setType(LiteralType.STRING_LITERAL);
			lit.setValue(s);
			printstatement.setPrintBody(lit);		
		}
	}
    |  log=LOG PAREN_LEFT valueExp = valueExpression PAREN_RIGHT (SEMI_COLON)?
	{
			printstatement.setPrintCommand("log");		
			printstatement.setPrintBody(valueExp);
            ParserUtil.setParseInfo(printstatement, log);
	} 
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}

/**
 *
 * Direct print command
 *
 */
directPrintCommand returns [String printcommand]
	@init{
		String s = null;
	 	StringBuffer buf = new StringBuffer();
	}
    @after{printcommand = s;}
	: (NEWLINE) (PAREN_LEFT n=number PAREN_RIGHT)? 
	{
     
        int count = n;
//        if (n != null) count = n;
		for (int i = 0; i < count; i++)
			buf.append("\r\n");
		s = buf.toString();
	}
	| SPACE (PAREN_LEFT n=number PAREN_RIGHT)?
	{
        int count = n;
		for (int i = 0; i < count; i++)
			buf.append(' ');
		s = buf.toString();
	}
	| TAB (PAREN_LEFT n=number PAREN_RIGHT)?
	{
        int count = n;
		for (int i = 0; i < count; i++)
			buf.append('\t');
		s = buf.toString();
	} 
	| INDENT (PAREN_LEFT PAREN_RIGHT)? {s = "indent";}
	| UNDENT (PAREN_LEFT PAREN_RIGHT)? {s = "undent";}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	

/**
 *
 * number - an integer number using by the direct print commands
 *
 */
number returns [int theCount]
	@init{
		int count = 1;
		String num = "";
	}
    @after {theCount = count;}
	: (i=INTEGER_LITERAL {num = num + i.getText();})+
	{
		count = Integer.parseInt(num);
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 			
		
/**
 *
 * parameters
 *
 */
parameters returns [Vector theParams]
	@init{
		Vector parameters = new Vector ();
	}		
    @after {theParams = parameters;}
	:	paren=PAREN_LEFT
	(parameter [parameters](COMMA parameter[parameters])*)?
	PAREN_RIGHT
	{
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		

/**
 *
 * parameter
 *
 */
parameter [Vector container]
	@init{
		MOFScriptParameter parameter = ParserUtil.getMofScriptModelFactory().createMOFScriptParameter();
        Token nextToken = null;
	}
	: {nextToken =getTokenStream().LT(1);} n=simpleName COLON t=type 
	{
	  parameter.setType (t);
	  parameter.setName (n);
	  ParserUtil.setParseInfo(parameter, nextToken);
	  container.add(parameter);
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}
	


/**
 *
 * valueExpression 
 *
 */
valueExpression returns [ValueExpression theExp]
	@init{
		ValueExpression exp = null;
	}
    @after{theExp = exp;}
    :
	(functionOrReference ARROW 'select') => sexp = selectExpression 
	{
		exp = sexp;
        ParserUtil.setParseInfo(exp, sexp);
	}		
    | (anyKindOfSimpleExpression arithmeticOperator)=> aexp=arithmeticExpression        
    {
      exp = aexp;
      ParserUtil.setParseInfo(exp, aexp);
    }
	| exp1=anyKindOfSimpleExpression
	{		
		exp = exp1;
		ParserUtil.setParseInfo(exp, exp1);
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

createExpression returns [CreateExpression theExp]
    @init {
       CreateExpression cexp  = ParserUtil.getMofScriptModelFactory().createCreateExpression();      
    }
    @after {
      theExp = cexp;
    }
    : create=CREATE theType=type PAREN_LEFT (params=createExpressionParameters {
	if (params != null) {
	    for (Iterator<CreateExpressionParameter> it = params.iterator(); it.hasNext();) {
		CreateExpressionParameter p = it.next();
		if (p != null)cexp.getParameters().add(p);
	    }
	}
    ParserUtil.setParseInfo(cexp, create);
       })? PAREN_RIGHT
    {
      cexp.setType(theType);
    } 
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

createExpressionParameters returns [Vector<CreateExpressionParameter> theParams]
    @init{
       Vector<CreateExpressionParameter> params = new Vector<CreateExpressionParameter>();       
    }
    @after {theParams = params;}
    : cep=createExpressionParameter {params.add(cep);} (COMMA cep=createExpressionParameter {params.add(cep);})*
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

createExpressionParameter returns [CreateExpressionParameter theExp]
    @init{
      CreateExpressionParameter param  = ParserUtil.getMofScriptModelFactory().createCreateExpressionParameter();
    }
    @after {theExp = param;}
    : n=simpleName eq=EQ v=anyKindOfSimpleExpression
    {
	param.setName(n);
	param.setValue(v);
    ParserUtil.setParseInfo(param, eq);
    }
    ;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

selectExpression returns [SelectExpression theExp]
	@init{
		SelectExpression exp = null;
	}
    @after {theExp = exp;}
	: funcOrRef = functionOrReference arrow=ARROW 'select' 
	PAREN_LEFT selectVar=simpleName (COLON selectType=type)? (PIPE logExp=filterSpec)? PAREN_RIGHT (DOT funName=simpleName fun=functionCallExpression[funName])?
	{
		exp = ParserUtil.getMofScriptModelFactory().createSelectExpression();
		exp.setVariable (selectVar);
		exp.setSourceReference (funcOrRef);
		if (selectType != null && !(selectType.equals("")))
			exp.setType (selectType);
		if (logExp != null) {
			exp.setFilterExpression (logExp);
		}
		if (fun != null) {
			exp.setAppliedFunction (fun);
		}	
        ParserUtil.setParseInfo(exp, arrow);
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 		
	

anyKindOfSimpleExpression returns [SimpleExpression theExp]
 : sexp=simpleExpression
 {
  theExp = sexp;
 }
 | slexp=stringLiteralSimpleExpression
 {
   theExp = slexp;
 }
 ;

/**
 *
 * A simple expression
 *
 */
simpleExpression returns [SimpleExpression theExp]
	@init{
		SimpleExpression exp = null;
	}
    @after {theExp = exp;}
	: fExp=functionOrReference {exp=fExp;}
	| leExp=nonStringLiteral {exp=leExp;}
		(		
	  dot=DOT sName=simpleName fc=functionCallExpression[sName] 
	    {
		  exp.getAdditionalExpressionPart().add(fc);
		  ParserUtil.setParseInfo(exp, dot);
		}
	  )*
	{
	}
	; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	
stringLiteralSimpleExpression returns [SimpleExpression theExp] 
	@init{
		SimpleExpression exp = null;
	}
    @after {theExp = exp;}
	: sexp = stringLiteral {exp = sexp;}
		(
		 DOT sName=simpleName fc=functionCallExpression[sName] 
	    {
		  exp.getAdditionalExpressionPart().add(fc);
		  ParserUtil.setParseInfo(exp, fc);
		}
	  )*	
	  ; 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

	  
functionOrReference returns [SimpleExpression theExp]
	@init{
		SimpleExpression exp = null;
        Token nextToken = null;
	}
    @after {theExp = exp;}
	: (scopedName PAREN_LEFT) => {nextToken = getTokenStream().LT(1);} sName=scopedName fExp=functionCallExpression[sName] {exp=fExp;}
	  {	  	
		  ParserUtil.setParseInfo(exp, nextToken);	  	
	  }
	(
		(DOT simpleName PAREN_LEFT) => dot=DOT sName2=simpleName extraExp=functionCallExpression[sName2]
		{
			exp.getAdditionalExpressionPart().add(extraExp);			
		}
		| DOT {nextToken = getTokenStream().LT(1);} sName2=simpleName
		{
			Reference ref =  ParserUtil.getMofScriptModelFactory().createReference();
			ParserUtil.setParseInfo(ref, nextToken);
			(ref).setName(sName2);
			exp.getAdditionalExpressionPart().add(ref);
		}
	)*
    /*
    | sName = scopedName colon=COLON varType=type
     ((EQ)=>EQ (logicalExpression | createExpression))?
    {
      // this is probably an erronous attempt of declaring a variable or property
		 MofScriptParseError error = new MofScriptParseError ("Error in variable/property declaration. Missing keyword 'var' or 'property'",
           colon.getLine(), colon.getCharPositionInLine(),  MofScriptParseError.MOFSCRIPT_ERROR);
		 ParserUtil.getModelChecker().getErrorManager().add(error);
      
    }
*/
	| {nextToken = getTokenStream().LT(1);} sName=scopedName 	
	{
		exp = ParserUtil.getMofScriptModelFactory().createReference();
		((Reference)exp).setName(sName);
		  ParserUtil.setParseInfo(exp, nextToken);	
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

	
/**
 *
 * Function call expression. The expression call part...
 *
 */
functionCallExpression [String sName] returns [FunctionCall theCall]
	@init{
		FunctionCall fcall = ParserUtil.getMofScriptModelFactory().createFunctionCall();
//		fcall.setName (sName);		
	}
    @after {theCall = fcall;}
	: paren=PAREN_LEFT  actualParameters[fcall] p=PAREN_RIGHT
	{
		// System.out.println ('Found FunctionCallExpression: ' + fcall.getName());	
		if (sName.toLowerCase().startsWith ("super.")) {
			fcall.setName (sName.substring(6));
			fcall.setIsSuperCall (true);
		} else {
			fcall.setName (sName);
			fcall.setIsSuperCall (false);
		}
        ParserUtil.setParseInfo(fcall, paren);
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

/**
 *
 * The parameters of a function call
 *
 */
actualParameters [FunctionCall call]	
	@init{	
	}
	:
	(param=actualParameter {
		call.getParameters().add(param);
	}(COMMA param=actualParameter {
		call.getParameters().add(param);
	})*)?
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	

/**
 *
 * The return type
 *
 */	
returnType returns [String ret=null]
	: tName=typeName {ret=tName;}
	| sName=scopedName {ret=sName;}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	

/**
 *
 * type
 *
 */	
type returns [String type]
	@init{String t = null;}
    @after{type = t;}
	: (simpleName DOT simpleName) => sName = scopedName {t=sName;}
	| (simpleName DOT typeName) => sType = scopedExistingType {t=sType;}
	| theType = typeName {t = theType;}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}			
	
/**
 *
 * A scoped name (<namepart> . <namepart>)
 *
 */
scopedName returns [String theName]    
    options{greedy=true;}
    @init {
        String fullName = "";
    }
    @after {
        theName = fullName;
    }
	: (simpleName DOT) => name=simpleName (DOT name2=simpleName {fullName = fullName + "." + name2;})+
	{
		fullName = name + fullName;
	}
	| name=simpleName {fullName=name;}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	
/**
 *
 * A name without any separators
 *
 */
simpleName returns [String theName]
	: n=SIMPLE_NAME
	{
		theName = n.getText();
	}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	

/**
 *
 * actual parameter
 *
 */	
actualParameter returns [ValueExpression theExp]
	: vExp=valueExpression 
    {theExp=vExp;
    }
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	
/**
 *
 * The direction of a parameter
 *
 */
parameterDirection returns [String paramDir]
    @init{
        String p = null;
    }
    @after{
        paramDir = p;
    }
	//: in:IN
	: in='in'
	{p=in.getText();}
	//| out:OUT
	| out='out'
	{p=out.getText();}
	;
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

		
/**
 *
 * a literal
 *
 */
nonStringLiteral returns [Literal theLit]
	@init{Literal lit = null;}
    @after{
        theLit = lit;
    }
	: ((MINUS)? INTEGER_LITERAL DOT INTEGER_LITERAL) => (munus=MINUS)? rlit=realLiteral
	{lit = rlit; if (minus!= null) lit.setValue("-" + lit.getValue());}    		
	| ((MINUS)? INTEGER_LITERAL) => (minus=MINUS)? ilit=integerLiteral
	{lit=ilit; if (minus!= null) lit.setValue("-" + lit.getValue());}
    | n=NULL_LITERAL
    {
		lit = ParserUtil.getMofScriptModelFactory().createLiteral();    	
    	lit.setType(LiteralType.NULL_LITERAL);
    	lit.setValue ("null");
        ParserUtil.setParseInfo(lit, n);
    }
    | blit=booleanLiteral	{lit=blit;}
	;		 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 
	

/**
  * String literal
  */
stringLiteral returns [Literal theLit]
  @init{
  	Literal lit = null;
  }
  @after {
    theLit = lit;
  }
  : s=STRING_LITERAL
  {
        String sn=ParserUtil.replaceEscapes(s.getText());
		lit = ParserUtil.getMofScriptModelFactory().createLiteral();		
		lit.setType(LiteralType.STRING_LITERAL);
	 	lit.setValue (sn.substring(1, sn.length() - 1));  	
        ParserUtil.setParseInfo(lit, s);
  }
  | s2=SPECIAL_STRING_LITERAL {
        String sn=ParserUtil.replaceEscapes(s2.getText());
		lit = ParserUtil.getMofScriptModelFactory().createLiteral();		
		lit.setType(LiteralType.STRING_LITERAL);
	 	lit.setValue (sn.substring(2, sn.length() - 2));
        ParserUtil.setParseInfo(lit, s2);
  }
  ;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}   

/**
 *
 * A boolean literal (true | false)
 *
 */
booleanLiteral returns [Literal theLit]
	@init{Literal lit = ParserUtil.getMofScriptModelFactory().createLiteral();}
	: b=BOOLEAN_LITERAL
	{
		lit.setType(LiteralType.BOOLEAN_LITERAL);
	 	lit.setValue (b.getText());		
        theLit = lit;
        ParserUtil.setParseInfo(lit, b);
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 	
	
	
/**
 *
 * Integer literal
 *
 */
integerLiteral returns [Literal theLit]
	@init{
		Literal lit = null;
	}
	: i=INTEGER_LITERAL
	{
		lit = ParserUtil.getMofScriptModelFactory().createLiteral();		
		lit.setType(LiteralType.INTEGER_LITERAL);
        lit.setValue (i.getText());		
        theLit = lit;
        ParserUtil.setParseInfo(lit, i);
	}
	;	 
	catch [RecognitionException rtex] {
		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	}	

/**
 *
 * Real literal
 *
 */
realLiteral returns [Literal theLit]
	@init{
		Literal lit = null;
	}
	: r=INTEGER_LITERAL DOT r2=INTEGER_LITERAL
    {
		lit = ParserUtil.getMofScriptModelFactory().createLiteral();    	
    	lit.setType(LiteralType.REAL_LITERAL);
       	lit.setValue (r.getText() + "." + r2.getText());		
        theLit = lit;
        ParserUtil.setParseInfo(lit, r);
    }	
    ;	 
	catch [RecognitionException rtex] {		// Handle exception
		MofScriptParseError error = new MofScriptParseError (rtex, this);
		ParserUtil.getModelChecker().getErrorManager().add(error); recover(input, rtex);
	} 

/*
options {
	k = 4;
	defaultErrorHandler=false;
	charVocabulary='\u0000'..'\uFFFE';
// 	testLiterals=true;
	//filter=true;
}
*/
TEXTTRANSFORMATION: 'texttransformation'|'textmodule';
FOREACH: 'forEach'
       ;
AND : ('and'|'&&')
    ;
OR  : ('or'|'||');

NOT: ('not'|'!');

STDOUT: 'stdout';
PRINT: 'print';
PRINTLN: 'println';
LOG: 'log';
UNPROTECT: 'unprotect';
NEWLINE: ('newline'|'nl');
SPACE: 'space';
TAB: 'tab';
INDENT:'indent';
UNDENT:'undent';
FILE:'file';
IF:'if';
ELSE:'else';
CREATE:'new';
WHILE:'while';
BREAK:'break';
RESULT:'result';
RETURN:'return';
IN:'in';
OUT:'out';
EXTENDS:'extends';
VAR:'var';
PROPERTY:'property';
ABSTRACT:'abstract';
MAIN:'main';
STRING: ('S'|'s')'tring';
BOOLEAN:('B'|'b')'oolean';
INTEGER:('I'|'i')'nteger';
REAL:('R'|'r')'eal';
HASHTABLE: ('H'|'h')'ashtable';
DICTIONARY: ('D'|'d')'ictionary';
LIST:('L'|'l')'ist';
OBJECT:('O'|'o')'bject';
MODULE:'module';
BETWEEN:'between';
ASPECT:'aspect';
POINTCUT:'pointcut';
EXECUTE:'execute';
CALL:'call';
TARGETPOINTCUT:'targetPointcut';
BEFORE:'before';
AFTER:'after';
AROUND:'around';
IMPORT:'import'|'access';
BOOLEAN_LITERAL
	: 'true'
	| 'false'
	;	

NULL_LITERAL
	: 'null'
	;	
	
STRING_LITERAL
	:	('"') (ESC | ~('\\'|'"'))* ('"')
	|   ('\'') (ESC | ~('\\'|'\''))* ('\'')
	;	
	
SPECIAL_STRING_LITERAL
	: 	'<%' (ESC | ~('\\' | '%'))* '%>'
	{
	}
    ;

SIMPLE_NAME
	: (ALPHA)(ALPHA | DIGIT | ZERO)*
	;


COMMENT : '//' ~('\n'|'\r')* (('\r'? '\n')|EOF)
	{ _channel = Token.HIDDEN_CHANNEL; 
	  String t = getText(); 
		MOFScriptComment comment = ParserUtil.getMofScriptModelFactory().createMOFScriptComment();
		comment.setCommentText(t);
		comment.setDocStyle(false);
		comment.setSingleLine(true);
		ParserUtil.addMOFScriptComment (comment);
	 }
	;	
	
ML_COMMENT :'/*' ( options {greedy=false;} : . )* '*/' 
   {_channel = Token.HIDDEN_CHANNEL;
    //System.out.println ("Comment: " + getText());
    MOFScriptComment comment = ParserUtil.getMofScriptModelFactory().createMOFScriptComment();
    comment.setCommentText(getText());
    comment.setDocStyle(false);
    comment.setSingleLine(false);
    ParserUtil.addMOFScriptComment (comment);			
   }
    ;
	
COLONCOLON
	: '::'
	;
COLON
	: ':'
	;
	
SEMI_COLON
	: ';'
	;
			
		
INTEGER_LITERAL
	: (DIGIT) (ZERO | DIGIT)*
	| ZERO
	{
		// System.out.println ("An Integer Literal");
	}
	;	
	
ARROW
    :
	'->'
	;

PAREN_LEFT
    :
	'('
	;

PAREN_RIGHT
    :
	')'
	;

SQUARE_LEFT
    :
	'['
	;

SQUARE_RIGHT
    :
	']'
	;
	
CURLY_LEFT
    :	'{'
	;

CURLY_RIGHT
    : '}'
	;

HASH
    : '#'
	;
	
STAR
    : '*'
	;

DIV
    : '/'
	;
	
MINUS
	: '-'
	;

PIPE
	: '|'
	;	
		
DOUBLE_EQ
	: '=='
	;

EQ
	: '='
	;

PLUS
    : '+'
	;	

NE
    : ('<>'|'!=')
	;

LE
    : '<='
	;

ALPHA_SIGN
    : '@'
	;


LT
    : '<'
	;

GT    
	: '>'
	;


GE
    : '>='
	;    
		
COMMA
	: ','
	;
	
DOT
	: '.'
	;	



fragment
DIGIT
	:	'1'..'9'
	;
	
fragment
ZERO
	: '0'
	;
	
fragment
ALPHA
	:	'a'..'z' 
	|	'A'..'Z'
	|	'_'
	;	

WS  :  (' '|'\r'|'\t'|'\u000C'|'\n') {_channel=Token.HIDDEN_CHANNEL;}
    ;

fragment 
ESC
	:	'\\'
		(	'n' // {$setText("\n");}
		|	'r' // {$setText("\r");}
		|	't' // {setText("\t");}
		|	'f' // {setText("\f");}
		|	'"' // {setText("\"");}
		|	'\'' // {setText("\'");}
		|	'\\' // {setText("\\");}
		)
	;
