/*=================================================
  *
  * Constructors
  *
  *=================================================
  */
 /**
  * Default constructor - creates argument based on the argument definition string.
  *
  * @param      argumentDefinitionString        Argument definition string, i.e.:
  *                                             <ul>
  *                                                <li>'x' - only argument name
  *                                                <li>'x=5' - argument name and argument value
  *                                                <li>'x=2*5' - argument name and argument value given as simple expression
  *                                                <li>'x=2*y' - argument name and argument expression (dependent argument 'x' on argument 'y')
  *                                             </ul>
  *
  * @param      elements   Optional parameters (comma separated) such as Arguments, Constants, Functions
  */
 public Argument(String argumentDefinitionString, params PrimitiveElement[] elements)
     : base(Argument.TYPE_ID)
 {
     if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.nameOnlyTokenRegExp)) {
         argumentName = argumentDefinitionString;
         argumentValue = ARGUMENT_INITIAL_VALUE;
         argumentType = FREE_ARGUMENT;
         argumentExpression = new Expression(elements);
     }
     else if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.constArgDefStrRegExp)) {
         HeadEqBody headEqBody = new HeadEqBody(argumentDefinitionString);
         argumentName = headEqBody.headTokens[0].tokenStr;
         Expression bodyExpr = new Expression(headEqBody.bodyStr);
         double bodyValue = bodyExpr.calculate();
         if ((bodyExpr.getSyntaxStatus() == Expression.NO_SYNTAX_ERRORS) && (bodyValue != Double.NaN)) {
             argumentExpression = new Expression();
             argumentValue = bodyValue;
             argumentType = FREE_ARGUMENT;
         }
         else {
             argumentExpression = bodyExpr;
             addDefinitions(elements);
             argumentType = DEPENDENT_ARGUMENT;
         }
     }
     else if (mXparser.regexMatch(argumentDefinitionString, ParserSymbol.functionDefStrRegExp)) {
         HeadEqBody headEqBody = new HeadEqBody(argumentDefinitionString);
         argumentName = headEqBody.headTokens[0].tokenStr;
         argumentExpression = new Expression(headEqBody.bodyStr, elements);
         argumentExpression.setDescription(headEqBody.headStr);
         argumentValue = ARGUMENT_INITIAL_VALUE;
         argumentType = DEPENDENT_ARGUMENT;
         n = new Argument(headEqBody.headTokens[2].tokenStr);
     }
     else {
         argumentValue = ARGUMENT_INITIAL_VALUE;
         argumentType = FREE_ARGUMENT;
         argumentExpression = new Expression();
         argumentExpression.setSyntaxStatus(SYNTAX_ERROR_OR_STATUS_UNKNOWN, "[" + argumentDefinitionString + "] " + "Invalid argument definition (patterns: 'x', 'x=5', 'x=5+3/2', 'x=2*y').");
     }
     setSilentMode();
     description = "";
 }
 /**
  * Constructor for function definition in natural math language,
  * for instance providing on string "f(x,y) = sin(x) + cos(x)"
  * is enough to define function "f" with parameters "x and y"
  * and function body "sin(x) + cos(x)".
  *
  * @param functionDefinitionString      Function definition in the form
  *                                      of one String, ie "f(x,y) = sin(x) + cos(x)"
  * @param elements                      Optional elements list (variadic - comma separated)
  *                                      of types: Argument, Constant, Function
  *
  * @see    PrimitiveElement
  *
  */
 public Function(String functionDefinitionString, params PrimitiveElement[] elements)
     : base(Function.TYPE_ID)
 {
     parametersNumber = 0;
     if (mXparser.regexMatch(functionDefinitionString, ParserSymbol.functionDefStrRegExp)) {
         HeadEqBody headEqBody = new HeadEqBody(functionDefinitionString);
         this.functionName = headEqBody.headTokens[0].tokenStr;
         functionExpression = new Expression(headEqBody.bodyStr, elements);
         functionExpression.setDescription(headEqBody.headStr);
         if (headEqBody.headTokens.Count > 1)
         {
             Token t;
             for (int i = 1; i < headEqBody.headTokens.Count; i++)
             {
                 t = headEqBody.headTokens[i];
                 if (t.tokenTypeId != ParserSymbol.TYPE_ID)
                     functionExpression.addArguments(new Argument(t.tokenStr));
             }
         }
         parametersNumber = functionExpression.getArgumentsNumber() - countRecursiveArguments();
         description = "";
         addFunctions(this);
     }
     else {
         functionExpression = new Expression();
         functionExpression.setDescription(functionDefinitionString);
         String errorMessage = ""; errorMessage = errorMessage + "\n [" + functionDefinitionString + "] " + "--> pattern not mathes: f(x1,...,xn) = ... reg exp: " + ParserSymbol.functionDefStrRegExp;
         functionExpression.setSyntaxStatus(Expression.SYNTAX_ERROR_OR_STATUS_UNKNOWN, errorMessage);
     }
 }
 /**
  * Constructor for function definition in natural math language,
  * for instance providing on string "f(x,y) = sin(x) + cos(x)"
  * is enough to define function "f" with parameters "x and y"
  * and function body "sin(x) + cos(x)".
  *
  * @param constantDefinitionString      Constant definition in the form
  *                                      of one String, ie "c = 2" or "c = 2*sin(pi/3)"
  * @param      elements   Optional parameters (comma separated) such as Arguments, Constants, Functions
  */
 public Constant(String constantDefinitionString, params PrimitiveElement[] elements)
     : base(Constant.TYPE_ID)
 {
     description = "";
     syntaxStatus = SYNTAX_ERROR_OR_STATUS_UNKNOWN;
     relatedExpressionsList = new List<Expression>();
     if (mXparser.regexMatch(constantDefinitionString, ParserSymbol.constArgDefStrRegExp))
     {
         HeadEqBody headEqBody = new HeadEqBody(constantDefinitionString);
         constantName = headEqBody.headTokens[0].tokenStr;
         Expression bodyExpression = new Expression(headEqBody.bodyStr, elements);
         constantValue = bodyExpression.calculate();
         syntaxStatus = bodyExpression.getSyntaxStatus();
         errorMessage = bodyExpression.getErrorMessage();
     }
     else errorMessage = "[" + constantDefinitionString + "] " + "--> pattern not mathes: " + ParserSymbol.constArgDefStrRegExp;
 }