Patch by John Scipione: Added cbrt() function to the supported functions

and factrorial expression support. Closes ticket #7945, thanks a bunch!


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42690 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2011-08-26 10:31:29 +00:00
parent a3ab429e07
commit 26fbe862cf
2 changed files with 46 additions and 24 deletions
@@ -59,6 +59,7 @@ class ExpressionParser {
int32 argumentCount);
MAPM _ParseFunction(const Token& token);
MAPM _ParseAtom();
MAPM _ParseFactorial(MAPM value);
void _EatToken(int32 type);
+45 -24
View File
@@ -33,6 +33,7 @@ enum {
TOKEN_MODULO,
TOKEN_POWER,
TOKEN_FACTORIAL,
TOKEN_OPENING_BRACKET,
TOKEN_CLOSING_BRACKET,
@@ -230,6 +231,9 @@ class Tokenizer {
case '^':
type = TOKEN_POWER;
break;
case '!':
type = TOKEN_FACTORIAL;
break;
case '(':
type = TOKEN_OPENING_BRACKET;
@@ -456,7 +460,7 @@ ExpressionParser::_ParseSum()
default:
fTokenizer->RewindToken();
return value;
return _ParseFactorial(value);
}
}
}
@@ -491,7 +495,7 @@ ExpressionParser::_ParseProduct()
default:
fTokenizer->RewindToken();
return value;
return _ParseFactorial(value);
}
}
}
@@ -506,7 +510,7 @@ ExpressionParser::_ParsePower()
Token token = fTokenizer->NextToken();
if (token.type != TOKEN_POWER) {
fTokenizer->RewindToken();
return value;
return _ParseFactorial(value);
}
value = value.pow(_ParseUnary());
}
@@ -565,9 +569,9 @@ MAPM
ExpressionParser::_ParseFunction(const Token& token)
{
if (strcasecmp("e", token.string.String()) == 0)
return MAPM(MM_E);
return _ParseFactorial(MAPM(MM_E));
else if (strcasecmp("pi", token.string.String()) == 0)
return MAPM(MM_PI);
return _ParseFactorial(MAPM(MM_PI));
// hard coded cases for different count of arguments
// supports functions with 3 arguments at most
@@ -576,68 +580,71 @@ ExpressionParser::_ParseFunction(const Token& token)
if (strcasecmp("abs", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].abs();
return _ParseFactorial(values[0].abs());
} else if (strcasecmp("acos", token.string.String()) == 0) {
_InitArguments(values, 1);
if (values[0] < -1 || values[0] > 1)
throw ParseException("out of domain", token.position);
return values[0].acos();
return _ParseFactorial(values[0].acos());
} else if (strcasecmp("asin", token.string.String()) == 0) {
_InitArguments(values, 1);
if (values[0] < -1 || values[0] > 1)
throw ParseException("out of domain", token.position);
return values[0].asin();
return _ParseFactorial(values[0].asin());
} else if (strcasecmp("atan", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].atan();
return _ParseFactorial(values[0].atan());
} else if (strcasecmp("atan2", token.string.String()) == 0) {
_InitArguments(values, 2);
return values[0].atan2(values[1]);
return _ParseFactorial(values[0].atan2(values[1]));
} else if (strcasecmp("cbrt", token.string.String()) == 0) {
_InitArguments(values, 1);
return _ParseFactorial(values[0].cbrt());
} else if (strcasecmp("ceil", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].ceil();
return _ParseFactorial(values[0].ceil());
} else if (strcasecmp("cos", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].cos();
return _ParseFactorial(values[0].cos());
} else if (strcasecmp("cosh", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].cosh();
return _ParseFactorial(values[0].cosh());
} else if (strcasecmp("exp", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].exp();
return _ParseFactorial(values[0].exp());
} else if (strcasecmp("floor", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].floor();
return _ParseFactorial(values[0].floor());
} else if (strcasecmp("ln", token.string.String()) == 0) {
_InitArguments(values, 1);
if (values[0] <= 0)
throw ParseException("out of domain", token.position);
return values[0].log();
return _ParseFactorial(values[0].log());
} else if (strcasecmp("log", token.string.String()) == 0) {
_InitArguments(values, 1);
if (values[0] <= 0)
throw ParseException("out of domain", token.position);
return values[0].log10();
return _ParseFactorial(values[0].log10());
} else if (strcasecmp("pow", token.string.String()) == 0) {
_InitArguments(values, 2);
return values[0].pow(values[1]);
return _ParseFactorial(values[0].pow(values[1]));
} else if (strcasecmp("sin", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].sin();
return _ParseFactorial(values[0].sin());
} else if (strcasecmp("sinh", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].sinh();
return _ParseFactorial(values[0].sinh());
} else if (strcasecmp("sqrt", token.string.String()) == 0) {
_InitArguments(values, 1);
if (values[0] < 0)
throw ParseException("out of domain", token.position);
return values[0].sqrt();
return _ParseFactorial(values[0].sqrt());
} else if (strcasecmp("tan", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].tan();
return _ParseFactorial(values[0].tan());
} else if (strcasecmp("tanh", token.string.String()) == 0) {
_InitArguments(values, 1);
return values[0].tanh();
return _ParseFactorial(values[0].tanh());
}
throw ParseException("unknown identifier", token.position);
@@ -652,7 +659,7 @@ ExpressionParser::_ParseAtom()
throw ParseException("unexpected end of expression", token.position);
if (token.type == TOKEN_CONSTANT)
return token.value;
return _ParseFactorial(token.value);
fTokenizer->RewindToken();
@@ -662,6 +669,20 @@ ExpressionParser::_ParseAtom()
_EatToken(TOKEN_CLOSING_BRACKET);
return _ParseFactorial(value);
}
MAPM
ExpressionParser::_ParseFactorial(MAPM value)
{
if (fTokenizer->NextToken().type == TOKEN_FACTORIAL) {
fTokenizer->RewindToken();
_EatToken(TOKEN_FACTORIAL);
return value.factorial();
}
fTokenizer->RewindToken();
return value;
}