/**
* (C) Copyright IBM Corp. 2010, 2015
*
* Licensed 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 com.ibm.bi.dml.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 com.ibm.bi.dml.parser.ConditionalPredicate;
import com.ibm.bi.dml.parser.DMLProgram;
import com.ibm.bi.dml.parser.DataIdentifier;
import com.ibm.bi.dml.parser.DoubleIdentifier;
import com.ibm.bi.dml.parser.Expression;
import com.ibm.bi.dml.parser.Expression.DataOp;
import com.ibm.bi.dml.parser.Expression.DataType;
import com.ibm.bi.dml.parser.Expression.ValueType;
import com.ibm.bi.dml.parser.antlr4.DmlParser.AddSubExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.AssignmentStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.AtomicExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.BooleanAndExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.BooleanNotExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.BooleanOrExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.BuiltinFunctionExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.CommandlineParamExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.CommandlinePositionExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ConstDoubleIdExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ConstFalseExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ConstIntIdExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ConstStringIdExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ConstTrueExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.DataIdExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.DataIdentifierContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.DmlprogramContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ExternalFunctionDefExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ForStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.FunctionCallAssignmentStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.FunctionCallMultiAssignmentStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.FunctionStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.IfStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.IfdefAssignmentStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ImportStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.IndexedExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.InternalFunctionDefExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.IterablePredicateColonExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.IterablePredicateSeqExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.MatrixDataTypeCheckContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.MatrixMulExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.Ml_typeContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ModIntDivExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.MultDivExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ParForStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ParameterizedExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.PathStatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.PowerExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.RelationalExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.SimpleDataIdentifierExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.StatementContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.StrictParameterizedExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.StrictParameterizedKeyValueStringContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.TypedArgNoAssignContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.UnaryExpressionContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.ValueTypeContext;
import com.ibm.bi.dml.parser.antlr4.DmlParser.WhileStatementContext;
import com.ibm.bi.dml.parser.AssignmentStatement;
import com.ibm.bi.dml.parser.BinaryExpression;
import com.ibm.bi.dml.parser.BooleanExpression;
import com.ibm.bi.dml.parser.BooleanIdentifier;
import com.ibm.bi.dml.parser.BuiltinFunctionExpression;
import com.ibm.bi.dml.parser.ConstIdentifier;
import com.ibm.bi.dml.parser.DataExpression;
import com.ibm.bi.dml.parser.ExternalFunctionStatement;
import com.ibm.bi.dml.parser.ForStatement;
import com.ibm.bi.dml.parser.FunctionCallIdentifier;
import com.ibm.bi.dml.parser.FunctionStatement;
import com.ibm.bi.dml.parser.IfStatement;
import com.ibm.bi.dml.parser.ImportStatement;
import com.ibm.bi.dml.parser.IndexedIdentifier;
import com.ibm.bi.dml.parser.IntIdentifier;
import com.ibm.bi.dml.parser.IterablePredicate;
import com.ibm.bi.dml.parser.LanguageException;
import com.ibm.bi.dml.parser.MultiAssignmentStatement;
import com.ibm.bi.dml.parser.OutputStatement;
import com.ibm.bi.dml.parser.ParForStatement;
import com.ibm.bi.dml.parser.ParameterExpression;
import com.ibm.bi.dml.parser.ParameterizedBuiltinFunctionExpression;
import com.ibm.bi.dml.parser.ParseException;
import com.ibm.bi.dml.parser.PathStatement;
import com.ibm.bi.dml.parser.PrintStatement;
import com.ibm.bi.dml.parser.RelationalExpression;
import com.ibm.bi.dml.parser.Statement;
import com.ibm.bi.dml.parser.StatementBlock;
import com.ibm.bi.dml.parser.StringIdentifier;
import com.ibm.bi.dml.parser.WhileStatement;
public class DmlSyntacticValidator implements DmlListener
{
private DmlSyntacticValidatorHelper helper = null;
private String _workingDir = "."; //current working directory
private String _currentPath = null; //current file path
private HashMap<String,String> argVals = null;
public DmlSyntacticValidator(DmlSyntacticValidatorHelper helper, String currentPath, HashMap<String,String> 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<ParameterExpression> paramExpression = new ArrayList<ParameterExpression>();
// 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<Expression> > exprList = new ArrayList< ArrayList<Expression> >();
ArrayList<Expression> rowIndices = new ArrayList<Expression>();
ArrayList<Expression> colIndices = new ArrayList<Expression>();
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<String, String> 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) {
String varName = ctx.getText().trim();
fillExpressionInfoCommandLineParameters(varName, ctx.dataInfo, ctx.start);
if(ctx.dataInfo.expr == null) {
// Check if the parent is ifdef
if(!(ctx.parent instanceof IfdefAssignmentStatementContext)) {
helper.notifyErrorListeners("the parameter " + varName + " either needs to be passed through commandline or initialized to default value", ctx.start);
}
}
}
@Override
public void exitCommandlinePositionExpression(CommandlinePositionExpressionContext ctx) {
String varName = ctx.getText().trim();
fillExpressionInfoCommandLineParameters(varName, ctx.dataInfo, ctx.start);
if(ctx.dataInfo.expr == null) {
// Check if the parent is ifdef
if(!(ctx.parent instanceof IfdefAssignmentStatementContext)) {
helper.notifyErrorListeners("the parameter " + varName + " either needs to be passed through commandline or initialized to default value", 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<String, DMLProgram>();
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<ParameterExpression> 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<ParameterExpression> 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<String, Expression> varParams = new HashMap<String, Expression>();
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<ParameterExpression> 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<ParameterExpression> 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<DataIdentifier> 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<ParameterExpression> 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<DataIdentifier> targetList = new ArrayList<DataIdentifier>();
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<String, String> 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<String, String> parForParamValues = new HashMap<String, String>();
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<DataIdentifier> getFunctionParameters(List<TypedArgNoAssignContext> ctx) {
ArrayList<DataIdentifier> retVal = new ArrayList<DataIdentifier>();
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<DataIdentifier> functionInputs = getFunctionParameters(ctx.inputParams);
functionStmt.setInputParams(functionInputs);
// set function outputs
ArrayList<DataIdentifier> 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<StatementBlock> body = new ArrayList<StatementBlock>();
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<DataIdentifier> functionInputs = getFunctionParameters(ctx.inputParams);
functionStmt.setInputParams(functionInputs);
// set function outputs
ArrayList<DataIdentifier> functionOutputs = getFunctionParameters(ctx.outputParams);
functionStmt.setOutputParams(functionOutputs);
// set function name
functionStmt.setName(ctx.name.getText());
// set other parameters
HashMap<String, String> otherParams = new HashMap<String,String>();
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<StatementBlock> body = new ArrayList<StatementBlock>();
// 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);
}
}