You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by du...@apache.org on 2016/01/21 02:06:23 UTC
[6/8] incubator-systemml git commit: [SYSTEMML-148] Refactored
.parser.{antlr4, python} to .parser.{dml, pydml}.
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/Dml.g4
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/Dml.g4 b/src/main/java/org/apache/sysml/parser/dml/Dml.g4
new file mode 100644
index 0000000..9d07dc9
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/Dml.g4
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+
+grammar Dml;
+
+@header
+{
+ // Commenting the package name and explicitly passing it in build.xml to maintain compatibility with maven plugin
+ // package org.apache.sysml.parser.dml;
+}
+
+// DML Program is a list of expression
+// For now, we only allow global function definitions (not nested or inside a while block)
+dmlprogram: (blocks+=statement | functionBlocks+=functionStatement)* EOF;
+
+statement returns [ StatementInfo info ]
+@init {
+ // This actions occurs regardless of how many alternatives in this rule
+ $info = new StatementInfo();
+} :
+ // ------------------------------------------
+ // ImportStatement
+ 'source' '(' filePath = STRING ')' 'as' namespace=ID ';'* # ImportStatement
+ | 'setwd' '(' pathValue = STRING ')' ';'* # PathStatement
+ // ------------------------------------------
+ // Treat function call as AssignmentStatement or MultiAssignmentStatement
+ // For backward compatibility and also since the behavior of foo() * A + foo() ... where foo returns A
+ // Convert FunctionCallIdentifier(paramExprs, ..) -> source
+ | // TODO: Throw an informative error if user doesnot provide the optional assignment
+ ( targetList+=dataIdentifier ('='|'<-') )? name=ID '(' (paramExprs+=parameterizedExpression (',' paramExprs+=parameterizedExpression)* )? ')' ';'* # FunctionCallAssignmentStatement
+ | '[' targetList+=dataIdentifier (',' targetList+=dataIdentifier)* ']' ('='|'<-') name=ID '(' (paramExprs+=parameterizedExpression (',' paramExprs+=parameterizedExpression)* )? ')' ';'* # FunctionCallMultiAssignmentStatement
+ // {notifyErrorListeners("Too many parentheses");}
+ // ------------------------------------------
+ // AssignmentStatement
+ | targetList+=dataIdentifier op=('<-'|'=') 'ifdef' '(' commandLineParam=dataIdentifier ',' source=expression ')' ';'* # IfdefAssignmentStatement
+ | targetList+=dataIdentifier op=('<-'|'=') source=expression ';'* # AssignmentStatement
+ // ------------------------------------------
+ // We don't support block statement
+ // | '{' body+=expression ';'* ( body+=expression ';'* )* '}' # BlockStatement
+ // ------------------------------------------
+ // IfStatement
+ | 'if' '(' predicate=expression ')' (ifBody+=statement ';'* | '{' (ifBody+=statement ';'*)* '}') ('else' (elseBody+=statement ';'* | '{' (elseBody+=statement ';'*)* '}'))? # IfStatement
+ // ------------------------------------------
+ // ForStatement & ParForStatement
+ | 'for' '(' iterVar=ID 'in' iterPred=iterablePredicate (',' parForParams+=strictParameterizedExpression)* ')' (body+=statement ';'* | '{' (body+=statement ';'* )* '}') # ForStatement
+ // Convert strictParameterizedExpression to HashMap<String, String> for parForParams
+ | 'parfor' '(' iterVar=ID 'in' iterPred=iterablePredicate (',' parForParams+=strictParameterizedExpression)* ')' (body+=statement ';'* | '{' (body+=statement ';'*)* '}') # ParForStatement
+ | 'while' '(' predicate=expression ')' (body+=statement ';'* | '{' (body+=statement ';'*)* '}') # WhileStatement
+ // ------------------------------------------
+;
+
+iterablePredicate returns [ ExpressionInfo info ]
+ @init {
+ // This actions occurs regardless of how many alternatives in this rule
+ $info = new ExpressionInfo();
+ } :
+ from=expression ':' to=expression #IterablePredicateColonExpression
+ | ID '(' from=expression ',' to=expression ',' increment=expression ')' #IterablePredicateSeqExpression
+ ;
+
+functionStatement returns [ StatementInfo info ]
+@init {
+ // This actions occurs regardless of how many alternatives in this rule
+ $info = new StatementInfo();
+} :
+ // ------------------------------------------
+ // FunctionStatement & ExternalFunctionStatement
+ // small change: only allow typed arguments here ... instead of data identifier
+ name=ID ('<-'|'=') 'function' '(' ( inputParams+=typedArgNoAssign (',' inputParams+=typedArgNoAssign)* )? ')' ( 'return' '(' ( outputParams+=typedArgNoAssign (',' outputParams+=typedArgNoAssign)* )? ')' )? '{' (body+=statement ';'*)* '}' # InternalFunctionDefExpression
+ | name=ID ('<-'|'=') 'externalFunction' '(' ( inputParams+=typedArgNoAssign (',' inputParams+=typedArgNoAssign)* )? ')' ( 'return' '(' ( outputParams+=typedArgNoAssign (',' outputParams+=typedArgNoAssign)* )? ')' )? 'implemented' 'in' '(' ( otherParams+=strictParameterizedKeyValueString (',' otherParams+=strictParameterizedKeyValueString)* )? ')' ';'* # ExternalFunctionDefExpression
+ // ------------------------------------------
+;
+
+
+// Other data identifiers are typedArgNoAssign, parameterizedExpression and strictParameterizedExpression
+dataIdentifier returns [ ExpressionInfo dataInfo ]
+@init {
+ // This actions occurs regardless of how many alternatives in this rule
+ $dataInfo = new ExpressionInfo();
+ // $dataInfo.expr = new org.apache.sysml.parser.DataIdentifier();
+} :
+ // ------------------------------------------
+ // IndexedIdentifier
+ name=ID '[' (rowLower=expression (':' rowUpper=expression)?)? ',' (colLower=expression (':' colUpper=expression)?)? ']' # IndexedExpression
+ // ------------------------------------------
+ | ID # SimpleDataIdentifierExpression
+ | COMMANDLINE_NAMED_ID # CommandlineParamExpression
+ | COMMANDLINE_POSITION_ID # CommandlinePositionExpression
+;
+expression returns [ ExpressionInfo info ]
+@init {
+ // This actions occurs regardless of how many alternatives in this rule
+ $info = new ExpressionInfo();
+ // $info.expr = new org.apache.sysml.parser.BinaryExpression(org.apache.sysml.parser.Expression.BinaryOp.INVALID);
+} :
+ // ------------------------------------------
+ // BinaryExpression
+ // power
+ <assoc=right> left=expression op='^' right=expression # PowerExpression
+ // unary plus and minus
+ | op=('-'|'+') left=expression # UnaryExpression
+ // sequence - since we are only using this into for
+ //| left=expression op=':' right=expression # SequenceExpression
+ // matrix multiply
+ | left=expression op='%*%' right=expression # MatrixMulExpression
+ // modulus and integer division
+ | left=expression op=('%/%' | '%%' ) right=expression # ModIntDivExpression
+ // arithmetic multiply and divide
+ | left=expression op=('*'|'/') right=expression # MultDivExpression
+ // arithmetic addition and subtraction
+ | left=expression op=('+'|'-') right=expression # AddSubExpression
+ // ------------------------------------------
+ // RelationalExpression
+ | left=expression op=('>'|'>='|'<'|'<='|'=='|'!=') right=expression # RelationalExpression
+ // ------------------------------------------
+ // BooleanExpression
+ // boolean not
+ | op='!' left=expression # BooleanNotExpression
+ // boolean and
+ | left=expression op=('&'|'&&') right=expression # BooleanAndExpression
+ // boolean or
+ | left=expression op=('|'|'||') right=expression # BooleanOrExpression
+
+ // ---------------------------------
+ // only applicable for builtin function expressions
+ | name=ID '(' (paramExprs+=parameterizedExpression (',' paramExprs+=parameterizedExpression)* )? ')' ';'* # BuiltinFunctionExpression
+
+ // 4. Atomic
+ | '(' left=expression ')' # AtomicExpression
+
+ // Should you allow indexed expression here ?
+ // | '[' targetList+=expression (',' targetList+=expression)* ']' # MultiIdExpression
+
+ // | BOOLEAN # ConstBooleanIdExpression
+ | 'TRUE' # ConstTrueExpression
+ | 'FALSE' # ConstFalseExpression
+ | INT # ConstIntIdExpression
+ | DOUBLE # ConstDoubleIdExpression
+ | STRING # ConstStringIdExpression
+ | dataIdentifier # DataIdExpression
+ // Special
+ // | 'NULL' | 'NA' | 'Inf' | 'NaN'
+;
+
+typedArgNoAssign : paramType=ml_type paramName=ID;
+parameterizedExpression : (paramName=ID '=')? paramVal=expression;
+strictParameterizedExpression : paramName=ID '=' paramVal=expression ;
+strictParameterizedKeyValueString : paramName=ID '=' paramVal=STRING ;
+ID : (ALPHABET (ALPHABET|DIGIT|'_')* '::')? ALPHABET (ALPHABET|DIGIT|'_')*
+ // Special ID cases:
+ // | 'matrix' // --> This is a special case which causes lot of headache
+ | 'as.scalar' | 'as.matrix' | 'as.double' | 'as.integer' | 'as.logical' | 'index.return' | 'lower.tail'
+;
+// Unfortunately, we have datatype name clashing with builtin function name: matrix :(
+// Therefore, ugly work around for checking datatype
+ml_type : valueType | dataType '[' valueType ']';
+// Note to reduce number of keywords, these are case-sensitive,
+// To allow case-insenstive, 'int' becomes: ('i' | 'I') ('n' | 'N') ('t' | 'T')
+valueType: 'int' | 'integer' | 'string' | 'boolean' | 'double'
+ | 'Int' | 'Integer' | 'String' | 'Boolean' | 'Double';
+dataType:
+ // 'scalar' # ScalarDataTypeDummyCheck
+ // |
+ ID # MatrixDataTypeCheck //{ if($ID.text.compareTo("matrix") != 0) { notifyErrorListeners("incorrect datatype"); } }
+ //| 'matrix' //---> See ID, this causes lot of headache
+ ;
+INT : DIGIT+ [Ll]?;
+// BOOLEAN : 'TRUE' | 'FALSE';
+DOUBLE: DIGIT+ '.' DIGIT* EXP? [Ll]?
+| DIGIT+ EXP? [Ll]?
+| '.' DIGIT+ EXP? [Ll]?
+;
+DIGIT: '0'..'9';
+ALPHABET : [a-zA-Z] ;
+fragment EXP : ('E' | 'e') ('+' | '-')? INT ;
+COMMANDLINE_NAMED_ID: '$' ALPHABET (ALPHABET|DIGIT|'_')*;
+COMMANDLINE_POSITION_ID: '$' DIGIT+;
+
+// supports single and double quoted string with escape characters
+STRING: '"' ( ESC | ~[\\"] )*? '"' | '\'' ( ESC | ~[\\'] )*? '\'';
+fragment ESC : '\\' [abtnfrv"'\\] ;
+// Comments, whitespaces and new line
+LINE_COMMENT : '#' .*? '\r'? '\n' -> skip ;
+MULTILINE_BLOCK_COMMENT : '/*' .*? '*/' -> skip ;
+WHITESPACE : (' ' | '\t' | '\r' | '\n')+ -> skip ;
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticErrorListener.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticErrorListener.java b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticErrorListener.java
new file mode 100644
index 0000000..027ea08
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticErrorListener.java
@@ -0,0 +1,115 @@
+/*
+ * 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.dml;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.sysml.api.DMLScript;
+
+import java.util.Stack;
+
+public class DmlSyntacticErrorListener {
+
+
+ private static final Log LOG = LogFactory.getLog(DMLScript.class.getName());
+
+ public static class CustomDmlErrorListener extends BaseErrorListener {
+
+ private boolean atleastOneError = false;
+ private Stack<String> currentFileName = new Stack<String>();
+
+ public void pushCurrentFileName(String currentFilePath) {
+ currentFileName.push(currentFilePath);
+ }
+
+ public String peekFileName() {
+ return currentFileName.peek();
+ }
+
+ public String popFileName() {
+ return currentFileName.pop();
+ }
+
+ public void validationError(int line, int charPositionInLine, String msg) {
+ try {
+ setAtleastOneError(true);
+ // Print error messages with file name
+ if(currentFileName == null || currentFileName.empty()) {
+ LOG.error("line "+line+":"+charPositionInLine+" "+msg);
+ }
+ else {
+ String fileName = currentFileName.peek();
+ LOG.error(fileName + " line "+line+":"+charPositionInLine+" "+msg);
+ }
+ }
+ catch(Exception e1) {
+ LOG.error("ERROR: while customizing error message:" + e1);
+ }
+ }
+
+ public void validationWarning(int line, int charPositionInLine, String msg) {
+ try {
+ //atleastOneError = true; ---> not an error, just warning
+ // Print error messages with file name
+ if(currentFileName == null || currentFileName.empty())
+ LOG.warn("line "+line+":"+charPositionInLine+" "+msg);
+ else {
+ String fileName = currentFileName.peek();
+ LOG.warn(fileName + " line "+line+":"+charPositionInLine+" "+msg);
+ }
+ }
+ catch(Exception e1) {
+ LOG.warn("ERROR: while customizing error message:" + e1);
+ }
+ }
+
+ @Override
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
+ int line, int charPositionInLine,
+ String msg, RecognitionException e)
+ {
+ try {
+ setAtleastOneError(true);
+ // Print error messages with file name
+ if(currentFileName == null || currentFileName.empty())
+ LOG.error("line "+line+":"+charPositionInLine+" "+msg);
+ else {
+ String fileName = currentFileName.peek();
+ LOG.error(fileName + " line "+line+":"+charPositionInLine+" "+msg);
+ }
+ }
+ catch(Exception e1) {
+ LOG.error("ERROR: while customizing error message:" + e1);
+ }
+ }
+
+ public boolean isAtleastOneError() {
+ return atleastOneError;
+ }
+
+ public void setAtleastOneError(boolean atleastOneError) {
+ this.atleastOneError = atleastOneError;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
new file mode 100644
index 0000000..798ab40
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
@@ -0,0 +1,1533 @@
+/*
+ * 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.dml;
+
+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.dml.DmlParser.AddSubExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.AssignmentStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.AtomicExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.BooleanAndExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.BooleanNotExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.BooleanOrExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.BuiltinFunctionExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.CommandlineParamExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.CommandlinePositionExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ConstDoubleIdExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ConstFalseExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ConstIntIdExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ConstStringIdExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ConstTrueExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.DataIdExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.DataIdentifierContext;
+import org.apache.sysml.parser.dml.DmlParser.DmlprogramContext;
+import org.apache.sysml.parser.dml.DmlParser.ExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ExternalFunctionDefExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ForStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.FunctionCallAssignmentStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.FunctionCallMultiAssignmentStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.FunctionStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.IfStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.IfdefAssignmentStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.ImportStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.IndexedExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.InternalFunctionDefExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.IterablePredicateColonExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.IterablePredicateSeqExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.MatrixDataTypeCheckContext;
+import org.apache.sysml.parser.dml.DmlParser.MatrixMulExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.Ml_typeContext;
+import org.apache.sysml.parser.dml.DmlParser.ModIntDivExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.MultDivExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ParForStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.ParameterizedExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.PathStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.PowerExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.RelationalExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.SimpleDataIdentifierExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.StatementContext;
+import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedKeyValueStringContext;
+import org.apache.sysml.parser.dml.DmlParser.TypedArgNoAssignContext;
+import org.apache.sysml.parser.dml.DmlParser.UnaryExpressionContext;
+import org.apache.sysml.parser.dml.DmlParser.ValueTypeContext;
+import org.apache.sysml.parser.dml.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<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) {
+ 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<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);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidatorHelper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidatorHelper.java b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidatorHelper.java
new file mode 100644
index 0000000..a1bd06f
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidatorHelper.java
@@ -0,0 +1,108 @@
+/*
+ * 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.dml;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.antlr.v4.runtime.Token;
+
+import org.apache.sysml.parser.DMLProgram;
+import org.apache.sysml.parser.dml.DmlParser.FunctionCallAssignmentStatementContext;
+import org.apache.sysml.parser.dml.DmlParser.ParameterizedExpressionContext;
+import org.apache.sysml.parser.dml.DmlSyntacticErrorListener.CustomDmlErrorListener;
+
+public class DmlSyntacticValidatorHelper {
+
+ private CustomDmlErrorListener _errorListener = null;
+
+ public DmlSyntacticValidatorHelper(CustomDmlErrorListener errorListener) {
+ this._errorListener = errorListener;
+ }
+
+ public void notifyErrorListeners(String message, int line, int charPositionInLine) {
+ this._errorListener.validationError(line, charPositionInLine, message);
+ }
+
+ public void notifyErrorListeners(String message, Token op) {
+ this._errorListener.validationError(op.getLine(), op.getCharPositionInLine(), message);
+ }
+
+ public void raiseWarning(String message, Token op) {
+ this._errorListener.validationWarning(op.getLine(), op.getCharPositionInLine(), message);
+ }
+
+ public String getCurrentFileName() {
+ return _errorListener.peekFileName();
+ }
+
+// public static void setInfoForArithmeticOp(org.apache.sysml.parser.Expression current,
+// org.apache.sysml.parser.Expression left,
+// org.apache.sysml.parser.Expression right, String opStr) {
+// try {
+// // PLUS, MINUS, MULT, DIV, MODULUS, INTDIV, MATMULT, POW, INVALID
+// org.apache.sysml.parser.Expression.BinaryOp bop = org.apache.sysml.parser.Expression.getBinaryOp(opStr);
+// current = new org.apache.sysml.parser.BinaryExpression(bop);
+// ((org.apache.sysml.parser.BinaryExpression)current).setLeft(left);
+// ((org.apache.sysml.parser.BinaryExpression)current).setRight(right);
+// ((org.apache.sysml.parser.BinaryExpression)current).setFilename(DmlSyntacticErrorListener.currentFileName.peek());
+// }
+// catch(Exception e) {
+// System.out.println("In setInfoForArithmeticOp>>");
+// e.printStackTrace();
+// }
+// }
+
+// public static void setInfoForBooleanOp(org.apache.sysml.parser.Expression current,
+// org.apache.sysml.parser.Expression left,
+// org.apache.sysml.parser.Expression right, String opStr) {
+// org.apache.sysml.parser.Expression.BooleanOp bop = org.apache.sysml.parser.Expression.getBooleanOp(opStr);
+// current = new org.apache.sysml.parser.BooleanExpression(bop);
+// ((org.apache.sysml.parser.BooleanExpression)current).setLeft(left);
+// ((org.apache.sysml.parser.BooleanExpression)current).setRight(right);
+// ((org.apache.sysml.parser.BooleanExpression)current).setFilename(DmlSyntacticErrorListener.currentFileName.peek());
+// }
+
+ public boolean validateBuiltinFunctions(FunctionCallAssignmentStatementContext ctx) {
+ String functionName = ctx.name.getText().replaceAll(" ", "").trim();
+ if(functionName.compareTo("write") == 0 || functionName.compareTo(DMLProgram.DEFAULT_NAMESPACE + "::write") == 0) {
+ return validateBuiltinWriteFunction(ctx);
+ }
+ return true;
+ }
+
+ private boolean validateBuiltinWriteFunction(FunctionCallAssignmentStatementContext ctx) {
+
+ return true;
+ }
+
+ public ArrayList<org.apache.sysml.parser.ParameterExpression> getParameterExpressionList(List<ParameterizedExpressionContext> paramExprs) {
+ ArrayList<org.apache.sysml.parser.ParameterExpression> retVal = new ArrayList<org.apache.sysml.parser.ParameterExpression>();
+ for(ParameterizedExpressionContext ctx : paramExprs) {
+ String paramName = null;
+ if(ctx.paramName != null && ctx.paramName.getText() != null && !ctx.paramName.getText().isEmpty()) {
+ paramName = ctx.paramName.getText();
+ }
+ org.apache.sysml.parser.ParameterExpression myArg = new org.apache.sysml.parser.ParameterExpression(paramName, ctx.paramVal.info.expr);
+ retVal.add(myArg);
+ }
+ return retVal;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/ExpressionInfo.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/ExpressionInfo.java b/src/main/java/org/apache/sysml/parser/dml/ExpressionInfo.java
new file mode 100644
index 0000000..436c409
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/ExpressionInfo.java
@@ -0,0 +1,31 @@
+/*
+ * 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.dml;
+
+
+public class ExpressionInfo {
+
+ public org.apache.sysml.parser.Expression expr = null;
+
+ // For parfor and for
+ public org.apache.sysml.parser.Expression from = null;
+ public org.apache.sysml.parser.Expression to = null;
+ public org.apache.sysml.parser.Expression increment = null;
+}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/dml/StatementInfo.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/StatementInfo.java b/src/main/java/org/apache/sysml/parser/dml/StatementInfo.java
new file mode 100644
index 0000000..fd4c50e
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/dml/StatementInfo.java
@@ -0,0 +1,36 @@
+/*
+ * 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.dml;
+
+import java.util.HashMap;
+import org.apache.sysml.parser.DMLProgram;
+
+public class StatementInfo {
+
+ public org.apache.sysml.parser.Statement stmt = null;
+
+ // Valid only for import statements
+ public HashMap<String,DMLProgram> namespaces = null;
+
+ // Valid only for function statement
+ //public String namespace = DMLProgram.DEFAULT_NAMESPACE;
+ public String functionName = "";
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-systemml/blob/c04fc99f/src/main/java/org/apache/sysml/parser/pydml/ExpressionInfo.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/pydml/ExpressionInfo.java b/src/main/java/org/apache/sysml/parser/pydml/ExpressionInfo.java
new file mode 100644
index 0000000..6cf5773
--- /dev/null
+++ b/src/main/java/org/apache/sysml/parser/pydml/ExpressionInfo.java
@@ -0,0 +1,32 @@
+/*
+ * 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.pydml;
+
+/**
+ * This class exists solely to prevent compiler warnings.
+ *
+ * <p>
+ * The ExpressionInfo and StatementInfo classes are shared among both parsers
+ * (R-like and Python-like dialects), and Antlr-generated code assumes that
+ * these classes are present in the parser's namespace.
+ */
+class ExpressionInfo extends org.apache.sysml.parser.dml.ExpressionInfo {
+
+}