/// <summary>
        /// Visit a function expression
        /// </summary>
        /// <param name="expression">The expression</param>
        /// <exception cref="ArgumentNullException">Thrown when the input parameter is null</exception>
        public void Visit(FunctionExpression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException("expression");
            }

            expression.Expression.Accept(this);
            object param = result;

            if (expression.FunctionName == "sizeof")
            {
                string customTypeName;
                int    symbolValue;
                if (param is string)
                {
                    if ((context.TryResolveCustomType((string)param, out customTypeName) &&
                         !DatatypeInfoProvider.IsPredefinedDatatype(customTypeName)) ||
                        param.ToString().StartsWith("enum", StringComparison.OrdinalIgnoreCase) ||
                        param.ToString().StartsWith("struct", StringComparison.OrdinalIgnoreCase) ||
                        param.ToString().StartsWith("union", StringComparison.OrdinalIgnoreCase))
                    {
                        result = "sizeof(" + param.ToString() + ")";
                    }
                    else
                    {
                        result = DatatypeInfoProvider.GetRpcDatatypeLength((string)param);
                    }
                }
                else if (context.TryResolveSymbol(expression.Text, out symbolValue))
                {
                    Type   value    = param.GetType();
                    string typeName = String.Empty;
                    switch (value.ToString())
                    {
                    case "System.Char":
                        typeName = "char";
                        break;

                    case "System.Byte":
                        typeName = "byte";
                        break;

                    case "System.Int16":
                        typeName = "short";
                        break;

                    case "System.Int32":
                        typeName = "int";
                        break;

                    case "System.Boolean":
                        typeName = "boolean";
                        break;

                    default:
                        break;
                    }

                    result = DatatypeInfoProvider.GetRpcDatatypeLength(typeName);
                }
                if (result is int &&
                    (int)result <= 0)
                {
                    throw new ExpressionEvaluatorException(
                              string.Format(CultureInfo.InvariantCulture, "cannot get the datatype length for the datatype '{0}'", param));
                }
            }
        }
        /// <summary>
        /// The Literal operation
        /// </summary>
        /// <returns>An expression node created based on the operation</returns>
        protected ExpressionNode Literal()
        {
            if (currentToken.Text.Length > 0)
            {
                if (currentToken.Type == TokenType.Integer)
                {
                    int res;
                    if (TryConvertNumber(currentToken.Text, out res))
                    {
                        ExpressionNode integer = new ExpressionNode(
                            new Token(TokenType.Integer, res.ToString(CultureInfo.InvariantCulture)));
                        GetNextToken();
                        return(integer);
                    }
                    else
                    {
                        throw new ExpressionEvaluatorException(
                                  string.Format(CultureInfo.InvariantCulture, "invalid number '{0}'", currentToken.Text));
                    }
                }
                else if (currentToken.Type == TokenType.String)
                {
                    int x;

                    if (!context.TryResolveSymbol(currentToken.Text, out x))
                    {
                        string tokenText = currentToken.Text;
                        while (true)
                        {
                            if (context.Variables != null &&
                                !context.Variables.ContainsKey(currentToken.Text) &&
                                !DatatypeInfoProvider.IsPredefinedDatatype(currentToken.Text) &&
                                !DatatypeInfoProvider.isPredefinedModifier(currentToken.Text))
                            {
                                string typeInfo;
                                if (context.TryResolveCustomType(currentToken.Text, out typeInfo))
                                {
                                    tokenText = typeInfo;
                                    break;
                                }
                                else
                                {
                                    context.ReportError(
                                        string.Format(CultureInfo.InvariantCulture, "cannot resolve symbol '{0}'", currentToken.Text));
                                    break;
                                }
                            }
                            if (context.Variables != null &&
                                context.Variables.ContainsKey(currentToken.Text))
                            {
                                tokenText = currentToken.Text;
                                break;
                            }

                            // treat predefinedModifier as empty node
                            if (DatatypeInfoProvider.isPredefinedModifier(currentToken.Text))
                            {
                                GetNextToken();
                            }
                            else if (DatatypeInfoProvider.IsPredefinedDatatype(currentToken.Text))
                            {
                                tokenText = currentToken.Text;
                                break;
                            }
                        }

                        // in order to get pointer type size and avoid related issue
                        bool isPointerType = false;
                        GetNextToken();
                        if (isInSizeOf)
                        {
                            while (currentToken.Text == "*")
                            {
                                GetNextToken();
                                isPointerType = true;
                            }
                        }

                        if (isPointerType)
                        {
                            ExpressionNode integer = new ExpressionNode(
                                new Token(TokenType.Integer, "4"));
                            return(integer);
                        }
                        ExpressionNode variable = new ExpressionNode(
                            new Token(TokenType.Variable, tokenText));

                        return(variable);
                    }
                    else if (isInSizeOf)
                    {
                        string tokenText = currentToken.Text;

                        GetNextToken();

                        //ignoring other expression
                        while (currentToken.Text != ")")
                        {
                            GetNextToken();
                        }

                        return(new ExpressionNode(
                                   new Token(TokenType.Variable, tokenText)));
                    }
                    else
                    {
                        GetNextToken();
                        return(new ExpressionNode(
                                   new Token(TokenType.Integer, x.ToString(CultureInfo.InvariantCulture))));
                    }
                }
                else
                {
                    throw new ExpressionEvaluatorException(
                              string.Format(CultureInfo.InvariantCulture, "unexpected token '{0}'", currentToken));
                }
            }
            else
            {
                throw new ExpressionEvaluatorException("unexpected end of input");
            }
        }