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:
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user