JVariableList::MatchResult JVariableList::FindUniqueVarName ( const JCharacter* prefix, JIndex* index, JString* maxPrefix ) const { assert( !JStringEmpty(prefix) ); const JSize count = GetElementCount(); JArray<JIndex> matchList; for (JIndex i=1; i<=count; i++) { const JString& name = GetVariableName(i); if (name == prefix) { *index = i; *maxPrefix = name; return kSingleMatch; } else if (JStringBeginsWith(name, name.GetLength(), prefix)) { matchList.AppendElement(i); } } const JSize matchCount = matchList.GetElementCount(); if (matchCount == 0) { *index = 0; maxPrefix->Clear(); return kNoMatch; } else if (matchCount == 1) { *index = matchList.GetElement(1); *maxPrefix = GetVariableName(*index); return kSingleMatch; } else { *maxPrefix = GetVariableName( matchList.GetElement(1) ); for (JIndex i=2; i<=matchCount; i++) { const JString& varName = GetVariableName( matchList.GetElement(i) ); const JSize matchLength = JCalcMatchLength(*maxPrefix, varName); const JSize prefixLength = maxPrefix->GetLength(); if (matchLength < prefixLength) { maxPrefix->RemoveSubstring(matchLength+1, prefixLength); } } *index = 0; return kMultipleMatch; } }
JParseResult JParseAsNegation ( const JCharacter* origExpr, const JSize origLength, const JVariableList* theVariableList, JDecision** theDecision ) { *theDecision = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // must start with "not " if (!JStringBeginsWith(expr, length, JPGetBooleanNOTString())) { return kJNotMyProblem; } // parse the rest of the string as a decision const JSize offset = JPGetBooleanNOTStringLength(); JDecision* arg = NULL; if (!JRecurseDecision(expr + offset, length - offset, theVariableList, &arg)) { return kJParseError; } // return JBooleanNOT object *theDecision = new JBooleanNOT(arg); assert( *theDecision != NULL ); return kJParsedOK; }
JParseResult JParseAsFunctionWithArgs ( const JCharacter* origExpr, const JSize origLength, const JVariableList* theVariableList, JFunction** theFunction, const JBoolean allowUIF ) { *theFunction = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // check if expr starts with a function name const JSize fnCount = JPGetStdFunctionCount(); const JStdFunctionInfo* fnInfo = JPGetStdFunctionInfo(); JBoolean found = kJFalse; JFunctionType type = kJSquareRootType; const JCharacter* argsStart = NULL; JSize argsLength = 0, argCount = 0, nameLength = 0; for (JIndex i=1; i<=fnCount; i++) { if (JStringBeginsWith(expr, length, fnInfo[i-1].name)) { found = kJTrue; type = fnInfo[i-1].type; argCount = fnInfo[i-1].argCount; nameLength = strlen(fnInfo[i-1].name); argsStart = expr + nameLength; argsLength = length - nameLength - 1; break; } } if (!found) { return kJNotMyProblem; } // check if the argument block is correctly closed if (!((*(expr + nameLength-1) == '(' && *(expr + length-1) == ')') || (*(expr + nameLength-1) == '[' && *(expr + length-1) == ']')) ) { return kJNotMyProblem; } // create the appropriate object JFunctionWithArgs* stdFunction = NULL; if (type == kJSquareRootType) { stdFunction = new JSquareRoot(); } else if (type == kJAbsValueType) { stdFunction = new JAbsValue(); } else if (type == kJSignType) { stdFunction = new JAlgSign(); } else if (type == kJRoundType) { stdFunction = new JRoundToInt(); } else if (type == kJTruncateType) { stdFunction = new JTruncateToInt(); } else if (type == kJLog10Type) { stdFunction = new JLogB(); // will set base later } else if (type == kJLogEType) { stdFunction = new JLogE(); } else if (type == kJLog2Type) { stdFunction = new JLogB(); // will set base later } else if (type == kJSineType) { stdFunction = new JSine(); } else if (type == kJCosineType) { stdFunction = new JCosine(); } else if (type == kJTangentType) { stdFunction = new JTangent(); } else if (type == kJArcSineType) { stdFunction = new JArcSine(); } else if (type == kJArcCosineType) { stdFunction = new JArcCosine(); } else if (type == kJArcTangentType) { stdFunction = new JArcTangent(); } else if (type == kJHypSineType) { stdFunction = new JHypSine(); } else if (type == kJHypCosineType) { stdFunction = new JHypCosine(); } else if (type == kJHypTangentType) { stdFunction = new JHypTangent(); } else if (type == kJArcHypSineType) { stdFunction = new JArcHypSine(); } else if (type == kJArcHypCosineType) { stdFunction = new JArcHypCosine(); } else if (type == kJArcHypTangentType) { stdFunction = new JArcHypTangent(); } else if (type == kJRealPartType) { stdFunction = new JRealPart(); } else if (type == kJImagPartType) { stdFunction = new JImagPart(); } else if (type == kJPhaseAngleType) { stdFunction = new JPhaseAngle(); } else if (type == kJConjugateType) { stdFunction = new JConjugate(); } else if (type == kJLogBType) { stdFunction = new JLogB(); } else if (type == kJArcTangent2Type) { stdFunction = new JArcTangent2(); } else if (type == kJRotateType) { stdFunction = new JRotateComplex(); } else if (type == kJMaxFuncType) { stdFunction = new JMaxFunc(); } else if (type == kJMinFuncType) { stdFunction = new JMinFunc(); } else if (type == kJParallelType) { stdFunction = new JParallel(); } else { cerr << "JParseAsFunctionWithArgs: unknown function type" << endl; return kJParseError; } assert( stdFunction != NULL ); // parse each argument const JCharacter* argSeparatorStr = JPGetArgSeparatorString(); const JSize argSeparatorLength = JPGetArgSeparatorStringLength(); if (argCount == 1) { // parse the entire string as the single argument JFunction* arg = NULL; const JBoolean ok = JRecurseFunction(argsStart, argsLength, theVariableList, &arg, allowUIF); if (ok && (type == kJLog10Type || type == kJLog2Type)) { JConstantValue* base = NULL; if (type == kJLog10Type) { base = new JConstantValue(10.0); } else if (type == kJLog2Type) { base = new JConstantValue(2.0); } assert( base != NULL ); stdFunction->SetArg(1, base); stdFunction->SetArg(2, arg); *theFunction = stdFunction; return kJParsedOK; } else if (ok) { stdFunction->SetArg(1, arg); *theFunction = stdFunction; return kJParsedOK; } else { delete stdFunction; return kJParseError; } } else if (argCount != kJUnlimitedArgs) { // parse all but the last argument by searching forward // for commas with JFindFirstOperator const JCharacter* argStart = argsStart; JSize remainderLength = argsLength; for (JIndex i=1; i<argCount; i++) { JSize offset; if (!JFindFirstOperator(argStart, remainderLength, argSeparatorStr, &offset)) { JString errorStr(expr, length); errorStr.Prepend("\""); errorStr += "\" has too few arguments"; (JGetUserNotification())->ReportError(errorStr); delete stdFunction; return kJParseError; } JFunction* arg = NULL; if (!JRecurseFunction(argStart, offset, theVariableList, &arg, allowUIF)) { delete stdFunction; return kJParseError; } stdFunction->SetArg(i, arg); argStart += offset + argSeparatorLength; remainderLength -= offset + argSeparatorLength; } // make sure that there is only one argument left JSize offset; if (JFindFirstOperator(argStart, remainderLength, argSeparatorStr, &offset)) { JString errorStr(expr, length); errorStr.Prepend("\""); errorStr += "\" has too many arguments"; (JGetUserNotification())->ReportError(errorStr); delete stdFunction; return kJParseError; } // parse the last argument in the list JFunction* arg = NULL; if (!JRecurseFunction(argStart, remainderLength, theVariableList, &arg, allowUIF)) { delete stdFunction; return kJParseError; } stdFunction->SetArg(argCount, arg); *theFunction = stdFunction; return kJParsedOK; } else // argCount == kJUnlimitedArgs { // parse all the arguments by searching forward // for commas with JFindFirstOperator JIndex i=1; const JCharacter* argStart = argsStart; JSize remainderLength = argsLength; JBoolean foundArgSeparator = kJTrue; while (foundArgSeparator) { JSize offset; foundArgSeparator = JFindFirstOperator(argStart, remainderLength, argSeparatorStr, &offset); if (!foundArgSeparator) { offset = remainderLength; } JFunction* arg = NULL; if (!JRecurseFunction(argStart, offset, theVariableList, &arg, allowUIF)) { delete stdFunction; return kJParseError; } stdFunction->SetArg(i, arg); i++; argStart += offset + argSeparatorLength; remainderLength -= offset + argSeparatorLength; } *theFunction = stdFunction; return kJParsedOK; } }
JParseResult JParseAsFunctionOfDiscrete ( const JCharacter* origExpr, const JSize origLength, const JVariableList* theVariableList, JFunction** theFunction, const JBoolean allowUIF ) { *theFunction = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // check if expr starts with a function name const JSize fnCount = JPGetFnOfDiscreteCount(); const JFunctionOfDiscreteInfo* fnInfo = JPGetFnOfDiscreteInfo(); JBoolean found = kJFalse; JFunctionType type = kJSquareRootType; const JCharacter* argStart = NULL; JSize argLength = 0, nameLength = 0; for (JSize i=1; i<=fnCount; i++) { if (JStringBeginsWith(expr, length, fnInfo[i-1].name)) { found = kJTrue; type = fnInfo[i-1].type; nameLength = strlen(fnInfo[i-1].name); argStart = expr + nameLength; argLength = length - nameLength - 1; } } if (!found) { return kJNotMyProblem; } // check if the argument block is correctly closed if (!((*(expr + nameLength-1) == '(' && *(expr + length-1) == ')') || (*(expr + nameLength-1) == '[' && *(expr + length-1) == ']')) ) { return kJNotMyProblem; } // parse the argument as a discrete variable name JIndex varIndex; JFunction* arrayIndex = NULL; const JParseResult result = JParseVariable(argStart, argLength, theVariableList, &varIndex, &arrayIndex, allowUIF); if (result != kJParsedOK || !theVariableList->IsDiscrete(varIndex)) { delete arrayIndex; JString errorStr(argStart, argLength); errorStr.Prepend("\""); errorStr += "\" is not a discrete variable"; (JGetUserNotification())->ReportError(errorStr); return kJParseError; } // create the appropriate object if (type == kJDiscVarValueIndexType) { *theFunction = new JDiscVarValueIndex(theVariableList, varIndex, arrayIndex); } else if (type == kJDiscVarValueType) { *theFunction = new JDiscVarValue(theVariableList, varIndex, arrayIndex); } else { cerr << "JParseAsFunctionOfDiscrete: unknown function type" << endl; delete arrayIndex; return kJParseError; } assert( *theFunction != NULL ); return kJParsedOK; }