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); int32 argumentCount);
MAPM _ParseFunction(const Token& token); MAPM _ParseFunction(const Token& token);
MAPM _ParseAtom(); MAPM _ParseAtom();
MAPM _ParseFactorial(MAPM value);
void _EatToken(int32 type); void _EatToken(int32 type);
+45 -24
View File
@@ -33,6 +33,7 @@ enum {
TOKEN_MODULO, TOKEN_MODULO,
TOKEN_POWER, TOKEN_POWER,
TOKEN_FACTORIAL,
TOKEN_OPENING_BRACKET, TOKEN_OPENING_BRACKET,
TOKEN_CLOSING_BRACKET, TOKEN_CLOSING_BRACKET,
@@ -230,6 +231,9 @@ class Tokenizer {
case '^': case '^':
type = TOKEN_POWER; type = TOKEN_POWER;
break; break;
case '!':
type = TOKEN_FACTORIAL;
break;
case '(': case '(':
type = TOKEN_OPENING_BRACKET; type = TOKEN_OPENING_BRACKET;
@@ -456,7 +460,7 @@ ExpressionParser::_ParseSum()
default: default:
fTokenizer->RewindToken(); fTokenizer->RewindToken();
return value; return _ParseFactorial(value);
} }
} }
} }
@@ -491,7 +495,7 @@ ExpressionParser::_ParseProduct()
default: default:
fTokenizer->RewindToken(); fTokenizer->RewindToken();
return value; return _ParseFactorial(value);
} }
} }
} }
@@ -506,7 +510,7 @@ ExpressionParser::_ParsePower()
Token token = fTokenizer->NextToken(); Token token = fTokenizer->NextToken();
if (token.type != TOKEN_POWER) { if (token.type != TOKEN_POWER) {
fTokenizer->RewindToken(); fTokenizer->RewindToken();
return value; return _ParseFactorial(value);
} }
value = value.pow(_ParseUnary()); value = value.pow(_ParseUnary());
} }
@@ -565,9 +569,9 @@ MAPM
ExpressionParser::_ParseFunction(const Token& token) ExpressionParser::_ParseFunction(const Token& token)
{ {
if (strcasecmp("e", token.string.String()) == 0) if (strcasecmp("e", token.string.String()) == 0)
return MAPM(MM_E); return _ParseFactorial(MAPM(MM_E));
else if (strcasecmp("pi", token.string.String()) == 0) 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 // hard coded cases for different count of arguments
// supports functions with 3 arguments at most // supports functions with 3 arguments at most
@@ -576,68 +580,71 @@ ExpressionParser::_ParseFunction(const Token& token)
if (strcasecmp("abs", token.string.String()) == 0) { if (strcasecmp("abs", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].abs(); return _ParseFactorial(values[0].abs());
} else if (strcasecmp("acos", token.string.String()) == 0) { } else if (strcasecmp("acos", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
if (values[0] < -1 || values[0] > 1) if (values[0] < -1 || values[0] > 1)
throw ParseException("out of domain", token.position); throw ParseException("out of domain", token.position);
return values[0].acos(); return _ParseFactorial(values[0].acos());
} else if (strcasecmp("asin", token.string.String()) == 0) { } else if (strcasecmp("asin", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
if (values[0] < -1 || values[0] > 1) if (values[0] < -1 || values[0] > 1)
throw ParseException("out of domain", token.position); throw ParseException("out of domain", token.position);
return values[0].asin(); return _ParseFactorial(values[0].asin());
} else if (strcasecmp("atan", token.string.String()) == 0) { } else if (strcasecmp("atan", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].atan(); return _ParseFactorial(values[0].atan());
} else if (strcasecmp("atan2", token.string.String()) == 0) { } else if (strcasecmp("atan2", token.string.String()) == 0) {
_InitArguments(values, 2); _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) { } else if (strcasecmp("ceil", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].ceil(); return _ParseFactorial(values[0].ceil());
} else if (strcasecmp("cos", token.string.String()) == 0) { } else if (strcasecmp("cos", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].cos(); return _ParseFactorial(values[0].cos());
} else if (strcasecmp("cosh", token.string.String()) == 0) { } else if (strcasecmp("cosh", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].cosh(); return _ParseFactorial(values[0].cosh());
} else if (strcasecmp("exp", token.string.String()) == 0) { } else if (strcasecmp("exp", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].exp(); return _ParseFactorial(values[0].exp());
} else if (strcasecmp("floor", token.string.String()) == 0) { } else if (strcasecmp("floor", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].floor(); return _ParseFactorial(values[0].floor());
} else if (strcasecmp("ln", token.string.String()) == 0) { } else if (strcasecmp("ln", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
if (values[0] <= 0) if (values[0] <= 0)
throw ParseException("out of domain", token.position); throw ParseException("out of domain", token.position);
return values[0].log(); return _ParseFactorial(values[0].log());
} else if (strcasecmp("log", token.string.String()) == 0) { } else if (strcasecmp("log", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
if (values[0] <= 0) if (values[0] <= 0)
throw ParseException("out of domain", token.position); throw ParseException("out of domain", token.position);
return values[0].log10(); return _ParseFactorial(values[0].log10());
} else if (strcasecmp("pow", token.string.String()) == 0) { } else if (strcasecmp("pow", token.string.String()) == 0) {
_InitArguments(values, 2); _InitArguments(values, 2);
return values[0].pow(values[1]); return _ParseFactorial(values[0].pow(values[1]));
} else if (strcasecmp("sin", token.string.String()) == 0) { } else if (strcasecmp("sin", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].sin(); return _ParseFactorial(values[0].sin());
} else if (strcasecmp("sinh", token.string.String()) == 0) { } else if (strcasecmp("sinh", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].sinh(); return _ParseFactorial(values[0].sinh());
} else if (strcasecmp("sqrt", token.string.String()) == 0) { } else if (strcasecmp("sqrt", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
if (values[0] < 0) if (values[0] < 0)
throw ParseException("out of domain", token.position); throw ParseException("out of domain", token.position);
return values[0].sqrt(); return _ParseFactorial(values[0].sqrt());
} else if (strcasecmp("tan", token.string.String()) == 0) { } else if (strcasecmp("tan", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].tan(); return _ParseFactorial(values[0].tan());
} else if (strcasecmp("tanh", token.string.String()) == 0) { } else if (strcasecmp("tanh", token.string.String()) == 0) {
_InitArguments(values, 1); _InitArguments(values, 1);
return values[0].tanh(); return _ParseFactorial(values[0].tanh());
} }
throw ParseException("unknown identifier", token.position); throw ParseException("unknown identifier", token.position);
@@ -652,7 +659,7 @@ ExpressionParser::_ParseAtom()
throw ParseException("unexpected end of expression", token.position); throw ParseException("unexpected end of expression", token.position);
if (token.type == TOKEN_CONSTANT) if (token.type == TOKEN_CONSTANT)
return token.value; return _ParseFactorial(token.value);
fTokenizer->RewindToken(); fTokenizer->RewindToken();
@@ -662,6 +669,20 @@ ExpressionParser::_ParseAtom()
_EatToken(TOKEN_CLOSING_BRACKET); _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; return value;
} }