JBoolean JIsNamedConstant ( const JCharacter* origExpr, const JSize origLength, JFunction** theFunction ) { *theFunction = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // check if expr is a named constant const JSize nameCount = JPGetNamedConstCount(); const JNamedConstInfo* nameInfo = JPGetNamedConstInfo(); for (JSize i=1; i<=nameCount; i++) { if (JStringsEqual(expr, length, nameInfo[i-1].name)) { *theFunction = new JNamedConstant(nameInfo[i-1].index); assert( *theFunction != NULL ); return kJTrue; } } return kJFalse; }
JBoolean JIsBoolConstant ( const JCharacter* origExpr, const JSize origLength, JDecision** theDecision ) { *theDecision = NULL; // remove enclosing parentheses const JCharacter* expr = origExpr; const JSize length = JStripParentheses(&expr, origLength); // check if expr is a known constant const JSize boolCount = JPGetBoolConstCount(); const JBoolConstInfo* boolInfo = JPGetBoolConstInfo(); for (JSize i=1; i<=boolCount; i++) { if (JStringsEqual(expr, length, boolInfo[i-1].name)) { *theDecision = new JBooleanConstant(boolInfo[i-1].value); assert( *theDecision != NULL ); return kJTrue; } } return kJFalse; }
JBoolean JVariableList::ParseVariableName ( const JCharacter* expr, const JSize exprLength, JIndex* index ) const { const JSize count = GetElementCount(); for (JIndex i=1; i<=count; i++) { const JString& name = GetVariableName(i); if (JStringsEqual(expr, exprLength, name)) { *index = i; return kJTrue; } } return kJFalse; }
JBoolean JVariableList::ParseDiscreteValue ( const JCharacter* expr, const JSize exprLength, const JIndex& variableIndex, JIndex* valueIndex ) const { const JSize count = GetDiscreteValueCount(variableIndex); for (JIndex i=1; i<=count; i++) { const JString& name = GetDiscreteValueName(variableIndex, i); if (JStringsEqual(expr, exprLength, name)) { *valueIndex = i; return kJTrue; } } return kJFalse; }
JBoolean JRecurseFunction ( 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); if (length == 0) { (JGetUserNotification())->ReportError("You specified an empty function"); return kJFalse; } // check for summation (+,-) JParseResult result = JParseAsSummation(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for product before division // so we correctly parse x/y*z as (x/y)*z result = JParseAsProduct(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for division result = JParseAsDivision(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for exponentiation result = JParseAsExponentiation(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for standard function result = JParseAsFunctionWithArgs(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for function of discrete variable result = JParseAsFunctionOfDiscrete(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for named constant if (JIsNamedConstant(expr, length, theFunction)) { return kJTrue; } // check for variable name result = JParseAsNumericVariable(expr, length, theVariableList, theFunction, allowUIF); if (result == kJParsedOK) { return kJTrue; } else if (result == kJParseError) { return kJFalse; } // check for empty JUserInputFunction if (allowUIF && JStringsEqual(expr, length, JUserInputFunction::GetEmptyString())) { *theFunction = new JUserInputFunction(theVariableList, JGetCurrFontManager(), JGetCurrColormap()); assert( *theFunction != NULL ); return kJTrue; } // check for constant, must occupy entire string JString valueStr(expr, length); JBoolean isPercentage = kJFalse; if (valueStr.GetLastCharacter() == '%') { isPercentage = kJTrue; valueStr.RemoveSubstring(valueStr.GetLength(), valueStr.GetLength()); valueStr.TrimWhitespace(); } JFloat value; if (valueStr.ConvertToFloat(&value)) { if (isPercentage) { value /= 100.0; } *theFunction = new JConstantValue(value); assert( *theFunction != NULL ); return kJTrue; } else if (jerrno() == ERANGE) { JString errorStr(expr, length); errorStr.Prepend("\""); errorStr += "\" is too large to be represented."; (JGetUserNotification())->ReportError(errorStr); return kJFalse; } // this string is not a function JString errorStr(expr, length); errorStr.Prepend("\""); errorStr += "\" is not a valid function."; (JGetUserNotification())->ReportError(errorStr); return kJFalse; }
JParseResult JParseAsDiscreteComparison ( 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); // search for equal sign JSize offset; if (!JStringContains(expr, length, JPGetEqualityString(), &offset)) { return kJNotMyProblem; } // check front part for a single variable name // if it doesn't work, we assume it's a function JIndex varIndex; JFunction* arrayIndex = NULL; const JParseResult result = JParseVariable(expr, offset, theVariableList, &varIndex, &arrayIndex); if (result != kJParsedOK) { return result; } // check last part for a legal variable value const JSize valueOffset = offset + JPGetEqualityStringLength(); const JCharacter* valueStart = expr + valueOffset; const JSize valueLength = JStripParentheses(&valueStart, length - valueOffset); JIndex value; if (theVariableList->IsNumeric(varIndex)) { // check for comparison with appropriate equivalent of "unknown" const JString& unknownName = theVariableList->GetUnknownValueSymbol(varIndex); if (JStringsEqual(valueStart, valueLength, unknownName)) { // return JValueUnknown object *theDecision = new JValueUnknown(theVariableList, varIndex, arrayIndex); assert( *theDecision != NULL ); return kJParsedOK; } else { delete arrayIndex; return kJNotMyProblem; } } else if (theVariableList->ParseDiscreteValue(valueStart, valueLength, varIndex, &value)) { // return JDiscreteEquality object *theDecision = new JDiscreteEquality(theVariableList, varIndex, arrayIndex, value); assert( *theDecision != NULL ); return kJParsedOK; } // check for another discrete variable JIndex varIndex2; JFunction* arrayIndex2 = NULL; const JParseResult result2 = JParseVariable(valueStart, valueLength, theVariableList, &varIndex2, &arrayIndex2); if (result2 == kJParsedOK && theVariableList->IsDiscrete(varIndex2) && theVariableList->HaveSameValues(varIndex, varIndex2)) { // return JDiscreteVarEquality object *theDecision = new JDiscreteVarEquality(theVariableList, varIndex, arrayIndex, varIndex2, arrayIndex2); assert( *theDecision != NULL ); return kJParsedOK; } delete arrayIndex; delete arrayIndex2; if (result2 == kJParsedOK) { // it parsed, but the variables can't be compared JString errorStr = theVariableList->GetVariableName(varIndex); errorStr += " cannot be compared with "; errorStr += JString(valueStart, valueLength); (JGetUserNotification())->ReportError(errorStr); return kJParseError; } else if (result2 == kJParseError) { return kJParseError; } else { // we couldn't make sense of the second half, so it's an error JString errorStr(valueStart, valueLength); errorStr.Prepend("\""); errorStr += "\" is not a possible value of "; errorStr += theVariableList->GetVariableName(varIndex); (JGetUserNotification())->ReportError(errorStr); return kJParseError; } }