org.apache.sysml.parser.antlr4.DmlSyntacticValidator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of systemml Show documentation
Show all versions of systemml Show documentation
Declarative Machine Learning
/*
* 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);
}
}