All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sysml.parser.antlr4.DmlSyntacticValidator Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.sysml.parser.antlr4;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.apache.sysml.parser.ConditionalPredicate;
import org.apache.sysml.parser.DMLProgram;
import org.apache.sysml.parser.DataIdentifier;
import org.apache.sysml.parser.DoubleIdentifier;
import org.apache.sysml.parser.Expression;
import org.apache.sysml.parser.Expression.DataOp;
import org.apache.sysml.parser.Expression.DataType;
import org.apache.sysml.parser.Expression.ValueType;
import org.apache.sysml.parser.antlr4.DmlParser.AddSubExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.AssignmentStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.AtomicExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.BooleanAndExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.BooleanNotExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.BooleanOrExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.BuiltinFunctionExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.CommandlineParamExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.CommandlinePositionExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ConstDoubleIdExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ConstFalseExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ConstIntIdExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ConstStringIdExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ConstTrueExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.DataIdExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.DataIdentifierContext;
import org.apache.sysml.parser.antlr4.DmlParser.DmlprogramContext;
import org.apache.sysml.parser.antlr4.DmlParser.ExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ExternalFunctionDefExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ForStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.FunctionCallAssignmentStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.FunctionCallMultiAssignmentStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.FunctionStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.IfStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.IfdefAssignmentStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.ImportStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.IndexedExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.InternalFunctionDefExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.IterablePredicateColonExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.IterablePredicateSeqExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.MatrixDataTypeCheckContext;
import org.apache.sysml.parser.antlr4.DmlParser.MatrixMulExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.Ml_typeContext;
import org.apache.sysml.parser.antlr4.DmlParser.ModIntDivExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.MultDivExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ParForStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.ParameterizedExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.PathStatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.PowerExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.RelationalExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.SimpleDataIdentifierExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.StatementContext;
import org.apache.sysml.parser.antlr4.DmlParser.StrictParameterizedExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.StrictParameterizedKeyValueStringContext;
import org.apache.sysml.parser.antlr4.DmlParser.TypedArgNoAssignContext;
import org.apache.sysml.parser.antlr4.DmlParser.UnaryExpressionContext;
import org.apache.sysml.parser.antlr4.DmlParser.ValueTypeContext;
import org.apache.sysml.parser.antlr4.DmlParser.WhileStatementContext;
import org.apache.sysml.parser.AParserWrapper;
import org.apache.sysml.parser.AssignmentStatement;
import org.apache.sysml.parser.BinaryExpression;
import org.apache.sysml.parser.BooleanExpression;
import org.apache.sysml.parser.BooleanIdentifier;
import org.apache.sysml.parser.BuiltinFunctionExpression;
import org.apache.sysml.parser.ConstIdentifier;
import org.apache.sysml.parser.DataExpression;
import org.apache.sysml.parser.ExternalFunctionStatement;
import org.apache.sysml.parser.ForStatement;
import org.apache.sysml.parser.FunctionCallIdentifier;
import org.apache.sysml.parser.FunctionStatement;
import org.apache.sysml.parser.IfStatement;
import org.apache.sysml.parser.ImportStatement;
import org.apache.sysml.parser.IndexedIdentifier;
import org.apache.sysml.parser.IntIdentifier;
import org.apache.sysml.parser.IterablePredicate;
import org.apache.sysml.parser.LanguageException;
import org.apache.sysml.parser.MultiAssignmentStatement;
import org.apache.sysml.parser.OutputStatement;
import org.apache.sysml.parser.ParForStatement;
import org.apache.sysml.parser.ParameterExpression;
import org.apache.sysml.parser.ParameterizedBuiltinFunctionExpression;
import org.apache.sysml.parser.ParseException;
import org.apache.sysml.parser.PathStatement;
import org.apache.sysml.parser.PrintStatement;
import org.apache.sysml.parser.RelationalExpression;
import org.apache.sysml.parser.Statement;
import org.apache.sysml.parser.StatementBlock;
import org.apache.sysml.parser.StringIdentifier;
import org.apache.sysml.parser.WhileStatement;

/**
 * TODO: Refactor duplicated parser code dml/pydml (entire package).
 *
 */
public class DmlSyntacticValidator implements DmlListener
{	
	private DmlSyntacticValidatorHelper helper = null;

	private String _workingDir = ".";   //current working directory 
	private String _currentPath = null; //current file path
	private HashMap argVals = null;
	
	public DmlSyntacticValidator(DmlSyntacticValidatorHelper helper, String currentPath, HashMap argVals) {
		this.helper = helper;
		this.argVals = argVals;
		
		_currentPath = currentPath;
	}
	
	// Functions we have to implement but don't really need it
	@Override
	public void enterAddSubExpression(AddSubExpressionContext ctx) { }
	@Override
	public void enterAssignmentStatement(AssignmentStatementContext ctx) {}
	@Override
	public void enterAtomicExpression(AtomicExpressionContext ctx) { }
	@Override
	public void enterBooleanAndExpression(BooleanAndExpressionContext ctx) { }
	@Override
	public void enterBooleanNotExpression(BooleanNotExpressionContext ctx) { }
	@Override
	public void enterBooleanOrExpression(BooleanOrExpressionContext ctx) { }
	@Override
	public void enterCommandlineParamExpression(CommandlineParamExpressionContext ctx) { }
	@Override
	public void enterCommandlinePositionExpression(CommandlinePositionExpressionContext ctx) { }	
	@Override
	public void enterConstDoubleIdExpression(ConstDoubleIdExpressionContext ctx) { }
	@Override
	public void enterConstIntIdExpression(ConstIntIdExpressionContext ctx) { }
	@Override
	public void enterConstStringIdExpression(ConstStringIdExpressionContext ctx) { }
	@Override
	public void enterDataIdExpression(DataIdExpressionContext ctx) { }

	@Override
	public void enterDmlprogram(DmlprogramContext ctx) { }
	@Override
	public void enterEveryRule(ParserRuleContext arg0) {
		if(arg0 instanceof StatementContext) {
			if(((StatementContext) arg0).info == null) {
				((StatementContext) arg0).info = new StatementInfo();
			}
		}
		if(arg0 instanceof FunctionStatementContext) {
			if(((FunctionStatementContext) arg0).info == null) {
				((FunctionStatementContext) arg0).info = new StatementInfo();
			}
		}
		if(arg0 instanceof ExpressionContext) {
			if(((ExpressionContext) arg0).info == null) {
				((ExpressionContext) arg0).info = new ExpressionInfo();
			}
		}
		if(arg0 instanceof DataIdentifierContext) {
			if(((DataIdentifierContext) arg0).dataInfo == null) {
				((DataIdentifierContext) arg0).dataInfo = new ExpressionInfo();
			}
		}
	}
	@Override
	public void enterExternalFunctionDefExpression(ExternalFunctionDefExpressionContext ctx) { }
	@Override
	public void enterForStatement(ForStatementContext ctx) {}
	@Override
	public void enterFunctionCallAssignmentStatement(FunctionCallAssignmentStatementContext ctx) { }
	@Override
	public void enterFunctionCallMultiAssignmentStatement(FunctionCallMultiAssignmentStatementContext ctx) { }
	@Override
	public void enterIfStatement(IfStatementContext ctx) { }
	@Override
	public void enterImportStatement(ImportStatementContext ctx) { }
	@Override
	public void enterIndexedExpression(IndexedExpressionContext ctx) { }
	@Override
	public void enterInternalFunctionDefExpression(InternalFunctionDefExpressionContext ctx) { }
	public void enterMatrixMulExpression(MatrixMulExpressionContext ctx) { }
	@Override
	public void enterMl_type(Ml_typeContext ctx) { }
	@Override
	public void enterModIntDivExpression(ModIntDivExpressionContext ctx) { }
	@Override
	public void enterMultDivExpression(MultDivExpressionContext ctx) { }
	@Override
	public void enterParameterizedExpression(ParameterizedExpressionContext ctx) { }
	@Override
	public void enterParForStatement(ParForStatementContext ctx) { }
	@Override
	public void enterPathStatement(PathStatementContext ctx) { }
	@Override
	public void enterPowerExpression(PowerExpressionContext ctx) { }
	@Override
	public void enterRelationalExpression(RelationalExpressionContext ctx) { }
	@Override
	public void enterSimpleDataIdentifierExpression(SimpleDataIdentifierExpressionContext ctx) { }
	@Override
	public void enterStrictParameterizedExpression(StrictParameterizedExpressionContext ctx) { }
	@Override
	public void enterTypedArgNoAssign(TypedArgNoAssignContext ctx) { }
	@Override
	public void enterUnaryExpression(UnaryExpressionContext ctx) { }
	@Override
	public void enterValueType(ValueTypeContext ctx) { }
	@Override
	public void enterWhileStatement(WhileStatementContext ctx) { }
	
	@Override
	public void visitErrorNode(ErrorNode arg0) { }
	@Override
	public void visitTerminal(TerminalNode arg0) { }
	@Override
	public void exitEveryRule(ParserRuleContext arg0) {}
	// --------------------------------------------------------------------
	private void setFileLineColumn(Expression expr, ParserRuleContext ctx) {
		// expr.setFilename(helper.getCurrentFileName());
		String txt = ctx.getText();
		expr.setFilename(_currentPath);
		expr.setBeginLine(ctx.start.getLine());
		expr.setBeginColumn(ctx.start.getCharPositionInLine());
		expr.setEndLine(ctx.stop.getLine());
		expr.setEndColumn(ctx.stop.getCharPositionInLine());
		if(expr.getBeginColumn() == expr.getEndColumn() && expr.getBeginLine() == expr.getEndLine() && txt.length() > 1) {
			expr.setEndColumn(expr.getBeginColumn() + txt.length() - 1);
		}
	}
	
	private void setFileLineColumn(Statement stmt, ParserRuleContext ctx) {
		String txt = ctx.getText();
		stmt.setFilename(helper.getCurrentFileName());
		stmt.setBeginLine(ctx.start.getLine());
		stmt.setBeginColumn(ctx.start.getCharPositionInLine());
		stmt.setEndLine(ctx.stop.getLine());
		stmt.setEndColumn(ctx.stop.getCharPositionInLine());
		if(stmt.getBeginColumn() == stmt.getEndColumn() && stmt.getBeginLine() == stmt.getEndLine() && txt.length() > 1) {
			stmt.setEndColumn(stmt.getBeginColumn() + txt.length() - 1);
		}
	}
	
	// For now do no type checking, let validation handle it.
	// This way parser doesn't have to open metadata file
	@Override
	public void exitAddSubExpression(AddSubExpressionContext ctx) {
		if(ctx.left.info.expr != null && ctx.right.info.expr != null) {
			Expression.BinaryOp bop = Expression.getBinaryOp(ctx.op.getText());
			ctx.info.expr = new BinaryExpression(bop);
			((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			((BinaryExpression)ctx.info.expr).setRight(ctx.right.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	@Override
	public void exitModIntDivExpression(ModIntDivExpressionContext ctx) {
		if(ctx.left.info.expr != null && ctx.right.info.expr != null) {
			Expression.BinaryOp bop = Expression.getBinaryOp(ctx.op.getText());
			ctx.info.expr = new BinaryExpression(bop);
			((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			((BinaryExpression)ctx.info.expr).setRight(ctx.right.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	
	@Override
	public void exitUnaryExpression(UnaryExpressionContext ctx) {
		if(ctx.left.info.expr != null) {
			String fileName = helper.getCurrentFileName();
			int line = ctx.start.getLine();
			int col = ctx.start.getCharPositionInLine();
			
			if(ctx.left.info.expr instanceof IntIdentifier) {
				if(ctx.op.getText().compareTo("-") == 0) {
					((IntIdentifier) ctx.left.info.expr).multiplyByMinusOne();
				}
				ctx.info.expr = ctx.left.info.expr;
			}
			else if(ctx.left.info.expr instanceof DoubleIdentifier) {
				if(ctx.op.getText().compareTo("-") == 0) {
					((DoubleIdentifier) ctx.left.info.expr).multiplyByMinusOne();
				}
				ctx.info.expr = ctx.left.info.expr;
			}
			else {
				Expression right = new IntIdentifier(1, fileName, line, col, line, col);
				if(ctx.op.getText().compareTo("-") == 0) {
					right = new IntIdentifier(-1, fileName, line, col, line, col);
				}
				
				Expression.BinaryOp bop = Expression.getBinaryOp("*");
				ctx.info.expr = new BinaryExpression(bop);
				((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
				((BinaryExpression)ctx.info.expr).setRight(right);
			}
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	
	@Override
	public void exitMultDivExpression(MultDivExpressionContext ctx) {
		Expression.BinaryOp bop = Expression.getBinaryOp(ctx.op.getText());
		ctx.info.expr = new BinaryExpression(bop);
		((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
		((BinaryExpression)ctx.info.expr).setRight(ctx.right.info.expr);
		setFileLineColumn(ctx.info.expr, ctx);
	}
	@Override
	public void exitPowerExpression(PowerExpressionContext ctx) {
		Expression.BinaryOp bop = Expression.getBinaryOp(ctx.op.getText());
		ctx.info.expr = new BinaryExpression(bop);
		((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
		((BinaryExpression)ctx.info.expr).setRight(ctx.right.info.expr);
		setFileLineColumn(ctx.info.expr, ctx);
	}
	
	@Override
	public void exitMatrixMulExpression(MatrixMulExpressionContext ctx) {
		Expression.BinaryOp bop = Expression.getBinaryOp(ctx.op.getText());
		ctx.info.expr = new BinaryExpression(bop);
		((BinaryExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
		((BinaryExpression)ctx.info.expr).setRight(ctx.right.info.expr);
		setFileLineColumn(ctx.info.expr, ctx);
	}

	// --------------------------------------------------------------------

	@Override
	public void exitRelationalExpression(RelationalExpressionContext ctx) {
		if(ctx.left.info.expr != null && ctx.right.info.expr != null) {
//			String fileName = helper.getCurrentFileName();
//			int line = ctx.start.getLine();
//			int col = ctx.start.getCharPositionInLine();
//			ArrayList paramExpression = new ArrayList();
//			paramExpression.add(new ParameterExpression(null, ctx.left.info.expr));
//			paramExpression.add(new ParameterExpression(null, ctx.right.info.expr));
//			ParameterExpression operator = new ParameterExpression(null, new StringIdentifier(ctx.op.getText(), fileName, line, col, line, col));
//			paramExpression.add(operator);
//			
//			try {
//				BuiltinFunctionExpression bife = BuiltinFunctionExpression.getBuiltinFunctionExpression("ppred", paramExpression, fileName, line, col, line, col);
//				if (bife != null){
//					// It is a builtin function
//					ctx.info.expr = bife;
//					return;
//				}
//			}
//			catch(Exception e) {}
//			helper.notifyErrorListeners("Cannot parse relational expression", ctx.getStart());
			
			Expression.RelationalOp rop = Expression.getRelationalOp(ctx.op.getText());
			ctx.info.expr = new RelationalExpression(rop);
			((RelationalExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			((RelationalExpression)ctx.info.expr).setRight(ctx.right.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	
	// --------------------------------------------------------------------
	
	@Override
	public void exitBooleanAndExpression(BooleanAndExpressionContext ctx) {
		if(ctx.left.info.expr != null && ctx.right.info.expr != null) {
			Expression.BooleanOp bop = Expression.getBooleanOp(ctx.op.getText());
			ctx.info.expr = new BooleanExpression(bop);
			((BooleanExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			((BooleanExpression)ctx.info.expr).setRight(ctx.right.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	
	@Override
	public void exitBooleanOrExpression(BooleanOrExpressionContext ctx) {
		if(ctx.left.info.expr != null && ctx.right.info.expr != null) {
			Expression.BooleanOp bop = Expression.getBooleanOp(ctx.op.getText());
			ctx.info.expr = new BooleanExpression(bop);
			((BooleanExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			((BooleanExpression)ctx.info.expr).setRight(ctx.right.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}

	@Override
	public void exitBooleanNotExpression(BooleanNotExpressionContext ctx) {
		if(ctx.left.info.expr != null) {
			Expression.BooleanOp bop = Expression.getBooleanOp(ctx.op.getText());
			ctx.info.expr = new BooleanExpression(bop);
			((BooleanExpression)ctx.info.expr).setLeft(ctx.left.info.expr);
			setFileLineColumn(ctx.info.expr, ctx);
		}
	}
	
	// --------------------------------------------------------------------
	
	@Override
	public void exitAtomicExpression(AtomicExpressionContext ctx) {
		ctx.info.expr = ctx.left.info.expr;
		setFileLineColumn(ctx.info.expr, ctx);
	}
	
//	@Override
//	public void exitConstBooleanIdExpression(ConstBooleanIdExpressionContext ctx) {
//		boolean val = false;
//		if(ctx.getText().compareTo("TRUE") == 0) {
//			val = true;
//		}
//		else if(ctx.getText().compareTo("FALSE") == 0) {
//			val = false;
//		}
//		else {
//			helper.notifyErrorListeners("cannot parse the boolean value: \'" +  ctx.getText() + "\'", ctx.getStart());
//			return;
//		}
//		int linePosition = ctx.start.getLine();
//		int charPosition = ctx.start.getCharPositionInLine();
//		ctx.info.expr = new BooleanIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
//		setFileLineColumn(ctx.info.expr, ctx);
//	}

	@Override
	public void exitConstDoubleIdExpression(ConstDoubleIdExpressionContext ctx) {
		try {
			double val = Double.parseDouble(ctx.getText());
			int linePosition = ctx.start.getLine();
			int charPosition = ctx.start.getCharPositionInLine();
			ctx.info.expr = new DoubleIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
			setFileLineColumn(ctx.info.expr, ctx);
		}
		catch(Exception e) {
			helper.notifyErrorListeners("cannot parse the double value: \'" +  ctx.getText() + "\'", ctx.getStart());
			return;
		}
	}

	@Override
	public void exitConstIntIdExpression(ConstIntIdExpressionContext ctx) {
		try {
			long val = Long.parseLong(ctx.getText());
			int linePosition = ctx.start.getLine();
			int charPosition = ctx.start.getCharPositionInLine();
			ctx.info.expr = new IntIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
			setFileLineColumn(ctx.info.expr, ctx);
		}
		catch(Exception e) {
			helper.notifyErrorListeners("cannot parse the integer value: \'" +  ctx.getText() + "\'", ctx.getStart());
			return;
		}
	}

	@Override
	public void exitConstStringIdExpression(ConstStringIdExpressionContext ctx) {
		String val = "";
		String text = ctx.getText();
		if(	(text.startsWith("\"") && text.endsWith("\"")) ||
			(text.startsWith("\'") && text.endsWith("\'"))) {
			if(text.length() > 2) {
				val = text.substring(1, text.length()-1);
			}
		}
		else {
			helper.notifyErrorListeners("something wrong while parsing string ... strange", ctx.start);
			return;
		}
			
		int linePosition = ctx.start.getLine();
		int charPosition = ctx.start.getCharPositionInLine();
		ctx.info.expr = new StringIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
		setFileLineColumn(ctx.info.expr, ctx);
	}
	
	// --------------------------------------------------------------------
	
	@Override
	public void exitDataIdExpression(DataIdExpressionContext ctx) {
		ctx.info.expr = ctx.dataIdentifier().dataInfo.expr;
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		ctx.info.expr.setAllPositions(helper.getCurrentFileName(), line, col, line, col);
		setFileLineColumn(ctx.info.expr, ctx);
//		if(ctx.getChild(0) instanceof DataIdentifierContext) {
//			ctx.info.expr = ctx.dataIdentifier().dataInfo.expr;
//		}
//		else {
//			String msg = "cannot evaluate data expression ... strange";
//			helper.notifyErrorListeners(msg, ctx.start);
//		}
	}
	
	@Override
	public void exitSimpleDataIdentifierExpression(SimpleDataIdentifierExpressionContext ctx) {
		// This is either a function, or variable with namespace
		// By default, it assigns to a data type
		ctx.dataInfo.expr = new DataIdentifier(ctx.getText());
		setFileLineColumn(ctx.dataInfo.expr, ctx);
	}
	
	@Override
	public void exitIndexedExpression(IndexedExpressionContext ctx) {
		ctx.dataInfo.expr = new IndexedIdentifier(ctx.name.getText(), false, false);
		setFileLineColumn(ctx.dataInfo.expr, ctx);
		try {
			ArrayList< ArrayList > exprList = new ArrayList< ArrayList >();
			
			ArrayList rowIndices = new ArrayList();
			ArrayList colIndices = new ArrayList();
			
			boolean isRowLower = (ctx.rowLower != null && !ctx.rowLower.isEmpty() && (ctx.rowLower.info.expr != null));
			boolean isRowUpper = (ctx.rowUpper != null && !ctx.rowUpper.isEmpty() && (ctx.rowUpper.info.expr != null));
			boolean isColLower = (ctx.colLower != null && !ctx.colLower.isEmpty() && (ctx.colLower.info.expr != null));
			boolean isColUpper = (ctx.colUpper != null && !ctx.colUpper.isEmpty() && (ctx.colUpper.info.expr != null));
			
			if(!isRowLower && !isRowUpper) {
				// both not set
				rowIndices.add(null); rowIndices.add(null);
			}
			else if(isRowLower && isRowUpper) {
				// both set
				rowIndices.add(ctx.rowLower.info.expr);
				rowIndices.add(ctx.rowUpper.info.expr);
			}
			else if(isRowLower && !isRowUpper) {
				// only row set
				rowIndices.add(ctx.rowLower.info.expr);
			}
			else {
				helper.notifyErrorListeners("incorrect index expression for row", ctx.start);
				return;
			}
			
			if(!isColLower && !isColUpper) {
				// both not set
				colIndices.add(null); colIndices.add(null);
			}
			else if(isColLower && isColUpper) {
				colIndices.add(ctx.colLower.info.expr);
				colIndices.add(ctx.colUpper.info.expr);
			}
			else if(isColLower && !isColUpper) {
				colIndices.add(ctx.colLower.info.expr);
			}
			else {
				helper.notifyErrorListeners("incorrect index expression for column", ctx.start);
				return;
			}
			
			
//			boolean rowIndexLowerSet = false;
//			boolean colIndexLowerSet = false;
//			
//			if(ctx.rowLower != null && !ctx.rowLower.isEmpty() && (ctx.rowLower.info.expr != null)) {
//				rowIndices.add(ctx.rowLower.info.expr);
//				rowIndexLowerSet = true;
//			}
//			else {
//				rowIndices.add(null);
//			}
//			if(ctx.rowUpper != null && !ctx.rowUpper.isEmpty() && (ctx.rowUpper.info.expr != null)) {
//				rowIndices.add(ctx.rowUpper.info.expr);
//				if(!rowIndexLowerSet) {
//					helper.notifyErrorListeners("incorrect index expression for row", ctx.start);
//					return;
//				}
//			}
//			if(ctx.colLower != null && !ctx.colLower.isEmpty() && (ctx.colLower.info.expr != null)) {
//				colIndices.add(ctx.colLower.info.expr);
//				colIndexLowerSet = true;
//			}
//			else {
//				colIndices.add(null);
//			}
//			if(ctx.colUpper != null && !ctx.colUpper.isEmpty() && (ctx.colUpper.info.expr != null)) {
//				colIndices.add(ctx.colUpper.info.expr);
//				if(!colIndexLowerSet) {
//					helper.notifyErrorListeners("incorrect index expression for column", ctx.start);
//					return;
//				}
//			}
			exprList.add(rowIndices);
			exprList.add(colIndices);
			((IndexedIdentifier) ctx.dataInfo.expr).setIndices(exprList);
		}
		catch(Exception e) {
			helper.notifyErrorListeners("cannot set the indices", ctx.start);
			return;
		}
	}
	
	private ConstIdentifier getConstIdFromString(String varValue, Token start) {
		// Both varName and varValue are correct
				int linePosition = start.getLine();
				int charPosition = start.getCharPositionInLine();
				try {
					long val = Long.parseLong(varValue);
					return new IntIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
				}
				catch(Exception e) {
					try {
						double val = Double.parseDouble(varValue);
						return new DoubleIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
					}
					catch(Exception e1) {
						try {
							if(varValue.compareTo("TRUE") == 0 || varValue.compareTo("FALSE") == 0) {
								boolean val = false;
								if(varValue.compareTo("TRUE") == 0) {
									val = true;
								}
								return new BooleanIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
							}
							else {
								String val = "";
								String text = varValue;
								if(	(text.startsWith("\"") && text.endsWith("\"")) ||
									(text.startsWith("\'") && text.endsWith("\'"))) {
									if(text.length() > 2) {
										val = text.substring(1, text.length()-1);
									}
								}
								else {
									val = text;
									// the commandline parameters can be passed without any quotes
//									helper.notifyErrorListeners("something wrong while parsing string ... strange", start);
//									return null;
								}
								return new StringIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
							}
						}
						catch(Exception e3) {
							helper.notifyErrorListeners("unable to cast the commandline parameter into int/double/boolean/string", start);
							return null;
						}
					}
				}
				
	}
	
	private void fillExpressionInfoCommandLineParameters(String varName, ExpressionInfo dataInfo, Token start) {
		
		if(!varName.startsWith("$")) {
			helper.notifyErrorListeners("commandline param doesnot start with $ ... strange", start);
			return;
		}
		
		String varValue = null;
		for(Map.Entry arg : this.argVals.entrySet()) {
			if(arg.getKey().trim().compareTo(varName) == 0) {
				if(varValue != null) {
					helper.notifyErrorListeners("multiple values passed for the parameter " + varName + " via commandline", start);
					return;
				}
				else {
					varValue = arg.getValue().trim();
				}
			}
		}
		
		if(varValue == null) {
			// helper.notifyErrorListeners("the parameter " + varName + " either needs to be passed through commandline or initialized to default value", start);
			return;
		}
		
		// Command line param cannot be empty string
		// If you want to pass space, please quote it
		if(varValue.trim().compareTo("") == 0)
			return;
		
		dataInfo.expr = getConstIdFromString(varValue, start);
	}
	
	@Override
	public void exitCommandlineParamExpression(CommandlineParamExpressionContext ctx) {
		handleCommandlineArgumentExpression(ctx);
	}

	@Override
	public void exitCommandlinePositionExpression(CommandlinePositionExpressionContext ctx) {
		handleCommandlineArgumentExpression(ctx);
	}
	
	/**
	 * 
	 * @param ctx
	 */
	private void handleCommandlineArgumentExpression(DataIdentifierContext ctx)
	{
		String varName = ctx.getText().trim();		
		fillExpressionInfoCommandLineParameters(varName, ctx.dataInfo, ctx.start);
		
		if(ctx.dataInfo.expr == null) {
			if(!(ctx.parent instanceof IfdefAssignmentStatementContext)) {
				String msg = "The parameter " + varName + " either needs to be passed "
						+ "through commandline or initialized to default value.";
				if( AParserWrapper.IGNORE_UNSPECIFIED_ARGS ) {
					ctx.dataInfo.expr = getConstIdFromString(" ", ctx.start);
					helper.raiseWarning(msg, ctx.start);
				}
				else {
					helper.notifyErrorListeners(msg, ctx.start);
				}
			}
		}
	}
	
	// --------------------------------------------------------------------
	
	@Override
	public void exitImportStatement(ImportStatementContext ctx) 
	{
		//prepare import filepath
		String filePath = ctx.filePath.getText();
		String namespace = DMLProgram.DEFAULT_NAMESPACE;
		if(ctx.namespace != null && ctx.namespace.getText() != null && !ctx.namespace.getText().isEmpty()) { 
			namespace = ctx.namespace.getText();
		}
		if((filePath.startsWith("\"") && filePath.endsWith("\"")) || 
				filePath.startsWith("'") && filePath.endsWith("'")) {	
			filePath = filePath.substring(1, filePath.length()-1);
		}
		
		//concatenate working directory to filepath
		filePath = _workingDir + File.separator + filePath;
		
		DMLProgram prog = null;
		try {
			prog = (new DMLParserWrapper()).doParse(filePath, null, argVals);
		} catch (ParseException e) {
			helper.notifyErrorListeners("Exception found during importing a program from file " + filePath, ctx.start);
			return;
		}
        // Custom logic whether to proceed ahead or not. Better than the current exception handling mechanism
		if(prog == null) {
			helper.notifyErrorListeners("One or more errors found during importing a program from file " + filePath, ctx.start);
			return;
		}
		else {
			ctx.info.namespaces = new HashMap();
			ctx.info.namespaces.put(namespace, prog);
			ctx.info.stmt = new ImportStatement();
			((ImportStatement) ctx.info.stmt).setCompletePath(filePath);
			((ImportStatement) ctx.info.stmt).setFilePath(ctx.filePath.getText());
			((ImportStatement) ctx.info.stmt).setNamespace(namespace);
		}
	}
	
	@Override
	public void exitAssignmentStatement(AssignmentStatementContext ctx) {
		if(ctx.targetList == null || ctx.targetList.size() != 1) {
			helper.notifyErrorListeners("incorrect parsing for assignment", ctx.start);
			return;
		}
		String targetListText = ctx.targetList.get(0).getText(); 
		if(targetListText.startsWith("$")) {
			helper.notifyErrorListeners("assignment of commandline parameters is not allowed. (Quickfix: try using someLocalVariable=ifdef(" + targetListText + ", default value))", ctx.start);
			return;
		}
		
		DataIdentifier target = null; 
		if(ctx.targetList.get(0).dataInfo.expr instanceof DataIdentifier) {
			target = (DataIdentifier) ctx.targetList.get(0).dataInfo.expr;
			Expression source = ctx.source.info.expr;
			
			int line = ctx.start.getLine();
			int col = ctx.start.getCharPositionInLine();
			try {
				ctx.info.stmt = new AssignmentStatement(target, source, line, col, line, col);
				setFileLineColumn(ctx.info.stmt, ctx);
			} catch (LanguageException e) {
				// TODO: extract more meaningful info from this exception.
				helper.notifyErrorListeners("invalid assignment", ctx.targetList.get(0).start);
				return;
			} 
		}
		else {
			helper.notifyErrorListeners("incorrect lvalue ... strange", ctx.targetList.get(0).start);
			return;
		}
		
	}

	
	private void setAssignmentStatement(DataIdentifier target, Expression expression, StatementContext ctx) {
		try {
			ctx.info.stmt = new AssignmentStatement(target, expression, ctx.start.getLine(), ctx.start.getCharPositionInLine(), ctx.start.getLine(), ctx.start.getCharPositionInLine());
			setFileLineColumn(ctx.info.stmt, ctx);
		} catch (LanguageException e) {
			// TODO: extract more meaningful info from this exception.
			helper.notifyErrorListeners("invalid function call", ctx.start);
			return;
		}
	}
	
	private void setPrintStatement(FunctionCallAssignmentStatementContext ctx, String functionName) {
		ArrayList paramExpression = helper.getParameterExpressionList(ctx.paramExprs);
		if(paramExpression.size() != 1) {
			helper.notifyErrorListeners(functionName + "() has only one parameter", ctx.start);
			return;
		}
		Expression expr = paramExpression.get(0).getExpr();
		if(expr == null) {
			helper.notifyErrorListeners("cannot process " + functionName + "() function", ctx.start);
			return;
		}
		try {
			int line = ctx.start.getLine();
			int col = ctx.start.getCharPositionInLine();
			ctx.info.stmt = new PrintStatement(functionName, expr, line, col, line, col);
			setFileLineColumn(ctx.info.stmt, ctx);
		} catch (LanguageException e) {
			helper.notifyErrorListeners("cannot process " + functionName + "() function", ctx.start);
			return;
		}
	}
	
	private void setOutputStatement(FunctionCallAssignmentStatementContext ctx) {
		ArrayList paramExpression = helper.getParameterExpressionList(ctx.paramExprs);
		if(paramExpression.size() < 2){
			helper.notifyErrorListeners("incorrect usage of write function (atleast 2 arguments required)", ctx.start);
			return;
		}
		if(paramExpression.get(0).getExpr() instanceof DataIdentifier) {
			//  && paramExpression.get(0).getName() == null
			// correct usage of identifier
			// if(paramExpression.get(1).getName() == null) {
				String fileName = helper.getCurrentFileName();
				int line = ctx.start.getLine();
				int col = ctx.start.getCharPositionInLine();
				HashMap varParams = new HashMap();
				varParams.put(DataExpression.IO_FILENAME, paramExpression.get(1).getExpr());
				for(int i = 2; i < paramExpression.size(); i++) {
					// DataExpression.FORMAT_TYPE, DataExpression.DELIM_DELIMITER, DataExpression.DELIM_HAS_HEADER_ROW,  DataExpression.DELIM_SPARSE
					varParams.put(paramExpression.get(i).getName(), paramExpression.get(i).getExpr());
				}
				
				DataExpression  dataExpression = new DataExpression(DataOp.WRITE, varParams, fileName, line, col, line, col);
				ctx.info.stmt = new  OutputStatement((DataIdentifier) paramExpression.get(0).getExpr(), DataOp.WRITE, fileName, line, col, line, col);
				setFileLineColumn(ctx.info.stmt, ctx);
				((OutputStatement)ctx.info.stmt).setExprParams(dataExpression);
				return;
			//}
		}
		
		helper.notifyErrorListeners("incorrect usage of write function", ctx.start);
		return;
		
	}
	
	@Override
	public void exitFunctionCallAssignmentStatement(FunctionCallAssignmentStatementContext ctx) {
		String fullyQualifiedFunctionName = ctx.name.getText();
		String [] fnNames = fullyQualifiedFunctionName.split("::");
		String functionName = "";
		String namespace = "";
		if(fnNames.length == 1) {
			namespace = DMLProgram.DEFAULT_NAMESPACE;
			functionName = fnNames[0].trim();
		}
		else if(fnNames.length == 2) {
			namespace = fnNames[0].trim();
			functionName = fnNames[1].trim();
		}
		else {
			helper.notifyErrorListeners("incorrect function name", ctx.name);
			return;
		}
		
		if((functionName.compareTo("print") == 0 || functionName.compareTo("stop") == 0 ) && namespace.compareTo(DMLProgram.DEFAULT_NAMESPACE) == 0) {
			setPrintStatement(ctx, functionName);
			return;
		}
		else if(functionName.compareTo("write") == 0
				&& namespace.compareTo(DMLProgram.DEFAULT_NAMESPACE) == 0) {
			setOutputStatement(ctx);
			return;
		}
		
		boolean ignoreLValue = false;
		if(ctx.targetList == null || ctx.targetList.size() == 0 || ctx.targetList.get(0).isEmpty()) {
			helper.notifyErrorListeners("function call needs to have lvalue (Quickfix: change it to \'tmpVar = " + functionName + "(...)\')", ctx.name);
			return;
		}
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		
		ArrayList paramExpression = helper.getParameterExpressionList(ctx.paramExprs);
//		if(functionName.compareTo("read") == 0 && paramExpression.size() > 0 && paramExpression.get(0).getName() == null) {
//			paramExpression.get(0).setName(DataExpression.IO_FILENAME);
//		}
		
		FunctionCallIdentifier functCall = new FunctionCallIdentifier(paramExpression);
		try {
			functCall.setFunctionName(functionName);
			functCall.setFunctionNamespace(namespace);
		} catch (ParseException e1) {
			helper.notifyErrorListeners("unable to process function " + functionName, ctx.start);
			 return;
		}
		
		DataIdentifier target = null; 
		if(!ignoreLValue) {
			if(ctx.targetList.get(0).dataInfo.expr instanceof DataIdentifier) {
				target = (DataIdentifier) ctx.targetList.get(0).dataInfo.expr;
			}
			else {
				helper.notifyErrorListeners("incorrect lvalue ... strange", ctx.targetList.get(0).start);
				//target = new DataIdentifier(); // so as not to avoid null pointer
				return;
			}
		}
		
		if(!functionName.contains("::") || functionName.startsWith(DMLProgram.DEFAULT_NAMESPACE)) {
			// In global namespace, so it can be a builtin function
			if(!helper.validateBuiltinFunctions(ctx)) {
				return; // it is a built-in function and validation failed, so donot proceed ahead.
			}
			// Double verification: verify passed function name is a (non-parameterized) built-in function.
			try {
				BuiltinFunctionExpression bife = BuiltinFunctionExpression.getBuiltinFunctionExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (bife != null){
					// It is a builtin function
					setAssignmentStatement(target, bife, ctx);
					return;
				}
				
				ParameterizedBuiltinFunctionExpression pbife = ParameterizedBuiltinFunctionExpression.getParamBuiltinFunctionExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (pbife != null){
					// It is a parameterized builtin function
					setAssignmentStatement(target, pbife, ctx);
					return;
				}
				
				// built-in read, rand ...
				DataExpression dbife = DataExpression.getDataExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (dbife != null){
					setAssignmentStatement(target, dbife, ctx);
					return;
				}
			} catch(Exception e) {
				helper.notifyErrorListeners("unable to process builtin function expression " + functionName  + ":" + e.getMessage(), ctx.start);
				return ;
			}
		}
		
		setAssignmentStatement(target, functCall, ctx);
	}
	
	@Override
	public void exitBuiltinFunctionExpression(BuiltinFunctionExpressionContext ctx) {
//		if(!helper.validateBuiltinFunctions(ctx)) {
//			return; // it is a built-in function and validation failed, so donot proceed ahead.
//		}
		// Double verification: verify passed function name is a (non-parameterized) built-in function.
		String functionName = ctx.name.getText();
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		ArrayList paramExpression = helper.getParameterExpressionList(ctx.paramExprs);
//		if(functionName.compareTo("read") == 0 && paramExpression.size() > 0 && paramExpression.get(0).getName() == null) {
//			paramExpression.get(0).setName(DataExpression.IO_FILENAME);
//		}
		
		try {
			BuiltinFunctionExpression bife = BuiltinFunctionExpression.getBuiltinFunctionExpression(functionName, paramExpression, fileName, line, col, line, col);
			if (bife != null){
				// It is a builtin function
				ctx.info.expr = bife;
				setFileLineColumn(ctx.info.expr, ctx);
				return;
			}
			
			ParameterizedBuiltinFunctionExpression pbife = ParameterizedBuiltinFunctionExpression.getParamBuiltinFunctionExpression(functionName, paramExpression, fileName, line, col, line, col);
			if (pbife != null){
				// It is a parameterized builtin function
				ctx.info.expr = pbife;
				setFileLineColumn(ctx.info.expr, ctx);
				return;
			}
			
			// built-in read, rand ...
			DataExpression dbife = DataExpression.getDataExpression(functionName, paramExpression, fileName, line, col, line, col);
			if (dbife != null){
				ctx.info.expr = dbife;
				setFileLineColumn(ctx.info.expr, ctx);
				return;
			}
			
		} catch(Exception e) {
			helper.notifyErrorListeners("unable to process builtin function expression " + functionName + ":" + e.getMessage(), ctx.start);
			return ;
		}
		helper.notifyErrorListeners("only builtin functions allowed as part of expression", ctx.start);
	}
	
	private void setMultiAssignmentStatement(ArrayList target, Expression expression, StatementContext ctx) {
		ctx.info.stmt = new MultiAssignmentStatement(target, expression);
		ctx.info.stmt.setAllPositions(helper.getCurrentFileName(), ctx.start.getLine(), ctx.start.getCharPositionInLine(), ctx.start.getLine(), ctx.start.getCharPositionInLine());
		setFileLineColumn(ctx.info.stmt, ctx);
	}

	@Override
	public void exitFunctionCallMultiAssignmentStatement(
			FunctionCallMultiAssignmentStatementContext ctx) {
		String fullyQualifiedFunctionName = ctx.name.getText();
		String [] fnNames = fullyQualifiedFunctionName.split("::");
		String functionName = "";
		String namespace = "";
		if(fnNames.length == 1) {
			namespace = DMLProgram.DEFAULT_NAMESPACE;
			functionName = fnNames[0].trim();
		}
		else if(fnNames.length == 2) {
			namespace = fnNames[0].trim();
			functionName = fnNames[1].trim();
		}
		else {
			helper.notifyErrorListeners("incorrect function name", ctx.name);
			return;
		}
		
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		
		ArrayList paramExpression = helper.getParameterExpressionList(ctx.paramExprs);
//		if(functionName.compareTo("read") == 0 && paramExpression.size() > 0 && paramExpression.get(0).getName() == null) {
//			paramExpression.get(0).setName(DataExpression.IO_FILENAME);
//		}
		
		FunctionCallIdentifier functCall = new FunctionCallIdentifier(paramExpression);
		try {
			functCall.setFunctionName(functionName);
			functCall.setFunctionNamespace(namespace);
		} catch (ParseException e1) {
			helper.notifyErrorListeners("unable to process function " + functionName, ctx.start);
			return;
		}
		
		ArrayList targetList = new ArrayList();
		for(DataIdentifierContext dataCtx : ctx.targetList) {
			if(dataCtx.dataInfo.expr instanceof DataIdentifier) {
				targetList.add((DataIdentifier) dataCtx.dataInfo.expr);
			}
			else {
				helper.notifyErrorListeners("incorrect lvalue ... strange", dataCtx.start);
				//target = new DataIdentifier(); // so as not to avoid null pointer
				return;
			}
		}
		
		if(!functionName.contains("::") || functionName.startsWith(DMLProgram.DEFAULT_NAMESPACE)) {
			// In global namespace, so it can be a builtin function
//			if(!helper.validateBuiltinFunctions(ctx)) {
//				return; // it is a built-in function and validation failed, so donot proceed ahead.
//			}
			// Double verification: verify passed function name is a (non-parameterized) built-in function.
			try {
				BuiltinFunctionExpression bife = BuiltinFunctionExpression.getBuiltinFunctionExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (bife != null){
					// It is a builtin function
					setMultiAssignmentStatement(targetList, bife, ctx);
					return;
				}
				
				ParameterizedBuiltinFunctionExpression pbife = ParameterizedBuiltinFunctionExpression.getParamBuiltinFunctionExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (pbife != null){
					// It is a parameterized builtin function
					setMultiAssignmentStatement(targetList, pbife, ctx);
					return;
				}
				
				// built-in read, rand ...
				DataExpression dbife = DataExpression.getDataExpression(functionName, functCall.getParamExprs(), fileName, line, col, line, col);
				if (dbife != null){
					setMultiAssignmentStatement(targetList, dbife, ctx);
					return;
				}
			} catch(Exception e) {
				helper.notifyErrorListeners("unable to process builtin function expression " + functionName  + ":" + e.getMessage(), ctx.start);
				return;
			}
		}
		
		setMultiAssignmentStatement(targetList, functCall, ctx);
	}
	
	private StatementBlock getStatementBlock(Statement current) {
		return DMLParserWrapper.getStatementBlock(current);
	}
	
	@Override
	public void exitIfStatement(IfStatementContext ctx) {
		IfStatement ifStmt = new IfStatement();
		ConditionalPredicate predicate = new ConditionalPredicate(ctx.predicate.info.expr);
		ifStmt.setConditionalPredicate(predicate);
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		ifStmt.setAllPositions(fileName, line, col, line, col);
		
		if(ctx.ifBody.size() > 0) {
			for(StatementContext stmtCtx : ctx.ifBody) {
				ifStmt.addStatementBlockIfBody(getStatementBlock(stmtCtx.info.stmt));
			}
			ifStmt.mergeStatementBlocksIfBody();
		}
		
		if(ctx.elseBody.size() > 0) {
			for(StatementContext stmtCtx : ctx.elseBody) {
				ifStmt.addStatementBlockElseBody(getStatementBlock(stmtCtx.info.stmt));
			}
			ifStmt.mergeStatementBlocksElseBody();
		}
		
		ctx.info.stmt = ifStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
	}
	
	@Override
	public void exitWhileStatement(WhileStatementContext ctx) {
		WhileStatement whileStmt = new WhileStatement();
		ConditionalPredicate predicate = new ConditionalPredicate(ctx.predicate.info.expr);
		whileStmt.setPredicate(predicate);
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		whileStmt.setAllPositions(fileName, line, col, line, col);
		
		if(ctx.body.size() > 0) {
			for(StatementContext stmtCtx : ctx.body) {
				whileStmt.addStatementBlock(getStatementBlock(stmtCtx.info.stmt));
			}
			whileStmt.mergeStatementBlocks();
		}
		
		ctx.info.stmt = whileStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
	}
	
	@Override
	public void exitForStatement(ForStatementContext ctx) {
		ForStatement forStmt = new ForStatement();
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		
		DataIdentifier iterVar = new DataIdentifier(ctx.iterVar.getText());
		HashMap parForParamValues = null;
		Expression incrementExpr = new IntIdentifier(1, fileName, line, col, line, col);
		if(ctx.iterPred.info.increment != null) {
			incrementExpr = ctx.iterPred.info.increment;
		}
		IterablePredicate predicate = new IterablePredicate(iterVar, ctx.iterPred.info.from, ctx.iterPred.info.to, incrementExpr, parForParamValues, fileName, line, col, line, col);
		forStmt.setPredicate(predicate);
		
		if(ctx.body.size() > 0) {
			for(StatementContext stmtCtx : ctx.body) {
				forStmt.addStatementBlock(getStatementBlock(stmtCtx.info.stmt));
			}
			forStmt.mergeStatementBlocks();
		}
		ctx.info.stmt = forStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
	}

	@Override
	public void exitParForStatement(ParForStatementContext ctx) {
		ParForStatement parForStmt = new ParForStatement();
		String fileName = helper.getCurrentFileName();
		int line = ctx.start.getLine();
		int col = ctx.start.getCharPositionInLine();
		
		DataIdentifier iterVar = new DataIdentifier(ctx.iterVar.getText());
		HashMap parForParamValues = new HashMap();
		if(ctx.parForParams != null && ctx.parForParams.size() > 0) {
			for(StrictParameterizedExpressionContext parForParamCtx : ctx.parForParams) {
				parForParamValues.put(parForParamCtx.paramName.getText(), parForParamCtx.paramVal.getText());
			}
		}
		
		Expression incrementExpr = new IntIdentifier(1, fileName, line, col, line, col);
		
		if( ctx.iterPred.info.increment != null ) {
			incrementExpr = ctx.iterPred.info.increment;
		}
		IterablePredicate predicate = new IterablePredicate(iterVar, ctx.iterPred.info.from, ctx.iterPred.info.to, incrementExpr, parForParamValues, fileName, line, col, line, col);
		parForStmt.setPredicate(predicate);
		if(ctx.body.size() > 0) {
			for(StatementContext stmtCtx : ctx.body) {
				parForStmt.addStatementBlock(getStatementBlock(stmtCtx.info.stmt));
			}
			parForStmt.mergeStatementBlocks();
		}
		ctx.info.stmt = parForStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
	}
	
	
	@Override
	public void exitDmlprogram(DmlprogramContext ctx) { }
	

	// ----------------------------------------------------------------------
	@Override
	public void exitValueType(ValueTypeContext ctx) { }
	@Override
	public void exitMl_type(Ml_typeContext ctx) { }
	
	private ArrayList getFunctionParameters(List ctx) {
		ArrayList retVal = new ArrayList();
		for(TypedArgNoAssignContext paramCtx : ctx) {
			DataIdentifier dataId = new DataIdentifier(paramCtx.paramName.getText());
			String dataType = null;
			String valueType = null;
			
			if(paramCtx.paramType == null || paramCtx.paramType.dataType() == null 
					|| paramCtx.paramType.dataType().getText() == null || paramCtx.paramType.dataType().getText().isEmpty()) {
				dataType = "scalar";
			}
			else {
				dataType = paramCtx.paramType.dataType().getText();
			}
			
			if(dataType.compareTo("matrix") == 0 || dataType.compareTo("Matrix") == 0) {
				// matrix
				dataId.setDataType(DataType.MATRIX);
			}
			else if(dataType.compareTo("scalar") == 0 || dataType.compareTo("Scalar") == 0) {
				// scalar
				dataId.setDataType(DataType.SCALAR);
			}
			else {
				helper.notifyErrorListeners("invalid datatype " + dataType, paramCtx.start);
				return null;
			}
			
			valueType = paramCtx.paramType.valueType().getText();
			if(valueType.compareTo("int") == 0 || valueType.compareTo("integer") == 0
				|| valueType.compareTo("Int") == 0 || valueType.compareTo("Integer") == 0) {
				dataId.setValueType(ValueType.INT);
			}
			else if(valueType.compareTo("string") == 0 || valueType.compareTo("String") == 0) {
				dataId.setValueType(ValueType.STRING);
			}
			else if(valueType.compareTo("boolean") == 0 || valueType.compareTo("Boolean") == 0) {
				dataId.setValueType(ValueType.BOOLEAN);
			}
			else if(valueType.compareTo("double") == 0 || valueType.compareTo("Double") == 0) {
				dataId.setValueType(ValueType.DOUBLE);
			}
			else if(valueType.compareTo("bool") == 0) {
				helper.notifyErrorListeners("invalid valuetype " + valueType + " (Quickfix: use \'boolean\' instead)", paramCtx.start);
				return null;
			}
			else {
				helper.notifyErrorListeners("invalid valuetype " + valueType, paramCtx.start);
				return null;
			}
			retVal.add(dataId);
		}
		return retVal;
	}
	
	@Override
	public void exitInternalFunctionDefExpression(InternalFunctionDefExpressionContext ctx) {
		FunctionStatement functionStmt = new FunctionStatement();
		
		ArrayList functionInputs  = getFunctionParameters(ctx.inputParams);
		functionStmt.setInputParams(functionInputs);
		
		// set function outputs
		ArrayList functionOutputs = getFunctionParameters(ctx.outputParams);
		functionStmt.setOutputParams(functionOutputs);
		
		// set function name
		functionStmt.setName(ctx.name.getText());
		
		
		if(ctx.body.size() > 0) {
			// handle function body
			// Create arraylist of one statement block
			ArrayList body = new ArrayList();
			for(StatementContext stmtCtx : ctx.body) {
				body.add(getStatementBlock(stmtCtx.info.stmt));
			}
			functionStmt.setBody(body);
			functionStmt.mergeStatementBlocks();
		}
		else {
			helper.notifyErrorListeners("functions with no statements are not allowed", ctx.start);
			return;
		}
		
		ctx.info.stmt = functionStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
		ctx.info.functionName = ctx.name.getText();
	}
	
	@Override
	public void exitExternalFunctionDefExpression(ExternalFunctionDefExpressionContext ctx) {
		ExternalFunctionStatement functionStmt = new ExternalFunctionStatement();
		
		ArrayList functionInputs  = getFunctionParameters(ctx.inputParams);
		functionStmt.setInputParams(functionInputs);
		
		// set function outputs
		ArrayList functionOutputs = getFunctionParameters(ctx.outputParams);
		functionStmt.setOutputParams(functionOutputs);
		
		// set function name
		functionStmt.setName(ctx.name.getText());
		
		// set other parameters
		HashMap otherParams = new HashMap();
		boolean atleastOneClassName = false;
		for(StrictParameterizedKeyValueStringContext otherParamCtx : ctx.otherParams){
			String paramName = otherParamCtx.paramName.getText();
			String val = "";
			String text = otherParamCtx.paramVal.getText();
			// First unquote the string
			if(	(text.startsWith("\"") && text.endsWith("\"")) ||
				(text.startsWith("\'") && text.endsWith("\'"))) {
				if(text.length() > 2) {
					val = text.substring(1, text.length()-1);
				}
				// Empty value allowed
			}
			else {
				helper.notifyErrorListeners("the value of user parameter for external function should be of type string", ctx.start);
				return;
			}
			otherParams.put(paramName, val);
			if(paramName.compareTo("classname") == 0) {
				atleastOneClassName = true;
			}
		}
		functionStmt.setOtherParams(otherParams);
		if(!atleastOneClassName) {
			helper.notifyErrorListeners("the parameter \'className\' needs to be passed for externalFunction", ctx.start);
			return;
		}
		
//		if(ctx.body.size() > 0) {
//			// handle function body
//			// Create arraylist of one statement block
//			ArrayList body = new ArrayList();
//			for(StatementContext stmtCtx : ctx.body) {
//				body.add(getStatementBlock(stmtCtx.info.stmt));
//			}
//			((ExternalFunctionStatement) functionStmt).setBody(body);
//			((ExternalFunctionStatement) functionStmt).mergeStatementBlocks();
//		}
//		else {
//			helper.notifyErrorListeners("functions with no statements are not allowed", ctx.start);
//			return;
//		}
		
		ctx.info.stmt = functionStmt;
		setFileLineColumn(ctx.info.stmt, ctx);
		ctx.info.functionName = ctx.name.getText();
	}
	
	
	@Override
	public void exitPathStatement(PathStatementContext ctx) {
		PathStatement stmt = new PathStatement(ctx.pathValue.getText());
		String filePath = ctx.pathValue.getText();
		if((filePath.startsWith("\"") && filePath.endsWith("\"")) || 
				filePath.startsWith("'") && filePath.endsWith("'")) {	
			filePath = filePath.substring(1, filePath.length()-1);
		}
		
		_workingDir = filePath;
		ctx.info.stmt = stmt;
	}
	
	@Override
	public void exitIfdefAssignmentStatement(IfdefAssignmentStatementContext ctx) {
		if(!ctx.commandLineParam.getText().startsWith("$")) {
			helper.notifyErrorListeners("the first argument of ifdef function should be a commandline argument parameter (which starts with $)", ctx.commandLineParam.start);
			return;
		}
		
		if(ctx.targetList == null || ctx.targetList.size() != 1) {
			helper.notifyErrorListeners("incorrect parsing for ifdef function", ctx.start);
			return;
		}
		String targetListText = ctx.targetList.get(0).getText(); 
		if(targetListText.startsWith("$")) {
			helper.notifyErrorListeners("lhs of ifdef function cannot be a commandline parameters. Use local variable instead", ctx.start);
			return;
		}
		
		DataIdentifier target = null; 
		if(ctx.targetList.get(0).dataInfo.expr instanceof DataIdentifier) {
			target = (DataIdentifier) ctx.targetList.get(0).dataInfo.expr;
			Expression source = null;
			if(ctx.commandLineParam.dataInfo.expr != null) {
				// Since commandline parameter is set
				// The check of following is done in fillExpressionInfoCommandLineParameters:
				// Command line param cannot be empty string
				// If you want to pass space, please quote it
				source = ctx.commandLineParam.dataInfo.expr;
			}
			else {
				source = ctx.source.info.expr;
			}
			
			int line = ctx.start.getLine();
			int col = ctx.start.getCharPositionInLine();
			try {
				ctx.info.stmt = new AssignmentStatement(target, source, line, col, line, col);
				setFileLineColumn(ctx.info.stmt, ctx);
			} catch (LanguageException e) {
				helper.notifyErrorListeners("invalid assignment for ifdef function", ctx.targetList.get(0).start);
				return;
			} 
			
		}
		else {
			helper.notifyErrorListeners("incorrect lvalue in ifdef function... strange", ctx.targetList.get(0).start);
			return;
		}
		
	}
	
	// ----------------------------------------------------------------------
	@Override
	public void exitParameterizedExpression(ParameterizedExpressionContext ctx) { }


	@Override
	public void exitStrictParameterizedExpression(StrictParameterizedExpressionContext ctx) { }

	@Override
	public void exitTypedArgNoAssign(TypedArgNoAssignContext ctx) { }
	@Override
	public void enterIfdefAssignmentStatement(IfdefAssignmentStatementContext ctx) { }
	@Override
	public void enterMatrixDataTypeCheck(MatrixDataTypeCheckContext ctx) { }
	@Override
	public void exitMatrixDataTypeCheck(MatrixDataTypeCheckContext ctx) {
		if(		ctx.ID().getText().compareTo("matrix") == 0 
				|| ctx.ID().getText().compareTo("Matrix") == 0 
				|| ctx.ID().getText().compareTo("Scalar") == 0
				|| ctx.ID().getText().compareTo("scalar") == 0
				) {
			// Do nothing
		}
		else {
			helper.notifyErrorListeners("incorrect datatype (expected matrix or scalar)", ctx.start);
		}
	}
	
	@Override
	public void enterBuiltinFunctionExpression(BuiltinFunctionExpressionContext ctx) {}
	@Override
	public void enterStrictParameterizedKeyValueString(StrictParameterizedKeyValueStringContext ctx) { }
	@Override
	public void exitStrictParameterizedKeyValueString(StrictParameterizedKeyValueStringContext ctx) {}
	@Override
	public void enterIterablePredicateColonExpression(IterablePredicateColonExpressionContext ctx) {}
	@Override
	public void enterIterablePredicateSeqExpression(IterablePredicateSeqExpressionContext ctx) { }
	
	@Override
	public void exitIterablePredicateColonExpression(IterablePredicateColonExpressionContext ctx) {
		ctx.info.from = ctx.from.info.expr;
		ctx.info.to = ctx.to.info.expr;
		ctx.info.increment = null;
	}
	
	@Override
	public void exitIterablePredicateSeqExpression(IterablePredicateSeqExpressionContext ctx) {
		if(ctx.ID().getText().compareTo("seq") != 0) {
			helper.notifyErrorListeners("incorrect function:\'" + ctx.ID().getText() + "\'. expected \'seq\'", ctx.start);
			return;
		}
		ctx.info.from = ctx.from.info.expr;
		ctx.info.to = ctx.to.info.expr;
		ctx.info.increment = ctx.increment.info.expr;		
	}
	
	@Override
	public void enterConstFalseExpression(ConstFalseExpressionContext ctx) { }
	@Override
	public void enterConstTrueExpression(ConstTrueExpressionContext ctx) { }
	
	@Override
	public void exitConstFalseExpression(ConstFalseExpressionContext ctx) {
		boolean val = false;
		int linePosition = ctx.start.getLine();
		int charPosition = ctx.start.getCharPositionInLine();
		ctx.info.expr = new BooleanIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
		setFileLineColumn(ctx.info.expr, ctx);
	}
	
	
	@Override
	public void exitConstTrueExpression(ConstTrueExpressionContext ctx) {
		boolean val = true;
		int linePosition = ctx.start.getLine();
		int charPosition = ctx.start.getCharPositionInLine();
		ctx.info.expr = new BooleanIdentifier(val, helper.getCurrentFileName(), linePosition, charPosition, linePosition, charPosition);
		setFileLineColumn(ctx.info.expr, ctx);
	}
	
		
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy