diff --git a/headers/private/shared/ExpressionParser.h b/headers/private/shared/ExpressionParser.h
index 5052448..9c835b3 100644
--- a/headers/private/shared/ExpressionParser.h
+++ b/headers/private/shared/ExpressionParser.h
@@ -59,6 +59,7 @@ class ExpressionParser {
 									int32 argumentCount);
 			MAPM				_ParseFunction(const Token& token);
 			MAPM				_ParseAtom();
+			MAPM				_ParseFactorial(MAPM value);
 
 			void				_EatToken(int32 type);
 
diff --git a/src/kits/shared/ExpressionParser.cpp b/src/kits/shared/ExpressionParser.cpp
index 549a46b..1b2658d 100644
--- a/src/kits/shared/ExpressionParser.cpp
+++ b/src/kits/shared/ExpressionParser.cpp
@@ -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;
 }
 
