/// <exception cref="System.SqlSyntaxErrorException" />
        private IExpression PrimaryExpression(string consumed
                                              , string consumedUp)
        {
            if (consumed != null)
            {
                return StartedFromIdentifier(consumed, consumedUp);
            }
            string tempStr;
            string tempStrUp;
            StringBuilder tempSb;
            Number tempNum;
            IExpression tempExpr;
            IExpression tempExpr2;
            IList<IExpression> tempExprList;
            switch (lexer.Token())
            {
                case MySqlToken.PlaceHolder:
                {
                    tempStr = lexer.GetStringValue();
                    tempStrUp = lexer.GetStringValueUppercase();
                    lexer.NextToken();
                    return CreatePlaceHolder(tempStr, tempStrUp);
                }

                case MySqlToken.LiteralBit:
                {
                    tempStr = lexer.GetStringValue();
                    lexer.NextToken();
                    return new LiteralBitField(null, tempStr).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralHex:
                {
                    var hex = new LiteralHexadecimal(null, lexer.Sql, lexer.OffsetCache, lexer.SizeCache, charset);
                    lexer.NextToken();
                    return hex.SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralBoolFalse:
                {
                    lexer.NextToken();
                    return new LiteralBoolean(false).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralBoolTrue:
                {
                    lexer.NextToken();
                    return new LiteralBoolean(true).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralNull:
                {
                    lexer.NextToken();
                    return new LiteralNull().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralNchars:
                {
                    tempSb = new StringBuilder();
                    do
                    {
                        lexer.AppendStringContent(tempSb);
                    } while (lexer.NextToken() == MySqlToken.LiteralChars);
                    return new LiteralString(null, tempSb.ToString(), true).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralChars:
                {
                    tempSb = new StringBuilder();
                    do
                    {
                        lexer.AppendStringContent(tempSb);
                    } while (lexer.NextToken() == MySqlToken.LiteralChars);
                    return new LiteralString(null, tempSb.ToString(), false).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralNumPureDigit:
                {
                    tempNum = lexer.GetIntegerValue();
                    lexer.NextToken();
                    return new LiteralNumber(tempNum).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralNumMixDigit:
                {
                    tempNum = lexer.GetDecimalValue();
                    lexer.NextToken();
                    return new LiteralNumber(tempNum).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.QuestionMark:
                {
                    var index = lexer.ParamIndex;
                    lexer.NextToken();
                    return CreateParam(index);
                }

                case MySqlToken.KwCase:
                {
                    lexer.NextToken();
                    return CaseWhenExpression();
                }

                case MySqlToken.KwInterval:
                {
                    lexer.NextToken();
                    return IntervalExpression();
                }

                case MySqlToken.KwExists:
                {
                    lexer.NextToken();
                    Match(MySqlToken.PuncLeftParen);
                    tempExpr = SubQuery();
                    Match(MySqlToken.PuncRightParen);
                    return new ExistsPrimary((IQueryExpression)tempExpr).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.UsrVar:
                {
                    tempStr = lexer.GetStringValue();
                    tempExpr = new UsrDefVarPrimary(tempStr).SetCacheEvalRst(cacheEvalRst);
                    if (lexer.NextToken() == MySqlToken.OpAssign)
                    {
                        lexer.NextToken();
                        tempExpr2 = Expression();
                        return new AssignmentExpression(tempExpr, tempExpr2);
                    }
                    return tempExpr;
                }

                case MySqlToken.SysVar:
                {
                    return SystemVariale();
                }

                case MySqlToken.KwMatch:
                {
                    lexer.NextToken();
                    return MatchExpression();
                }

                case MySqlToken.PuncLeftParen:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.KwSelect)
                    {
                        tempExpr = SubQuery();
                        Match(MySqlToken.PuncRightParen);
                        return tempExpr;
                    }
                    tempExpr = Expression();
                    switch (lexer.Token())
                    {
                        case MySqlToken.PuncRightParen:
                        {
                            lexer.NextToken();
                            return tempExpr;
                        }

                        case MySqlToken.PuncComma:
                        {
                            lexer.NextToken();
                            tempExprList = new List<IExpression>();
                            tempExprList.Add(tempExpr);
                            tempExprList = ExpressionList(tempExprList);
                            return new RowExpression(tempExprList).SetCacheEvalRst(cacheEvalRst);
                        }

                        default:
                        {
                            throw Err("unexpected token: " + lexer.Token());
                        }
                    }
                    //goto case MySqlToken.KwUtcDate;
                }

                case MySqlToken.KwUtcDate:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new UtcDate(null).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwUtcTime:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new UtcTime(null).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwUtcTimestamp:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new UtcTimestamp(null).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwCurrentDate:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new Curdate().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwCurrentTime:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new Curtime().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwCurrentTimestamp:
                case MySqlToken.KwLocaltime:
                case MySqlToken.KwLocaltimestamp:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new Now().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwCurrentUser:
                {
                    lexer.NextToken();
                    if (lexer.Token() == MySqlToken.PuncLeftParen)
                    {
                        lexer.NextToken();
                        Match(MySqlToken.PuncRightParen);
                    }
                    return new CurrentUser().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwDefault:
                {
                    if (lexer.NextToken() == MySqlToken.PuncLeftParen)
                    {
                        return OrdinaryFunction(lexer.GetStringValue(), lexer.GetStringValueUppercase());
                    }
                    return new DefaultValue().SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwDatabase:
                case MySqlToken.KwIf:
                case MySqlToken.KwInsert:
                case MySqlToken.KwLeft:
                case MySqlToken.KwRepeat:
                case MySqlToken.KwReplace:
                case MySqlToken.KwRight:
                case MySqlToken.KwSchema:
                case MySqlToken.KwValues:
                {
                    tempStr = lexer.GetStringValue();
                    tempStrUp = lexer.GetStringValueUppercase();
                    var tempStrUp2 = lexer.Token().KeyWordToString();
                    if (!tempStrUp2.Equals(tempStrUp))
                    {
                        tempStrUp = tempStr = tempStrUp2;
                    }
                    if (lexer.NextToken() == MySqlToken.PuncLeftParen)
                    {
                        return OrdinaryFunction(tempStr, tempStrUp);
                    }
                    throw Err("keyword not followed by '(' is not expression: " + tempStr);
                }

                case MySqlToken.KwMod:
                {
                    lexer.NextToken();
                    Match(MySqlToken.PuncLeftParen);
                    tempExpr = Expression();
                    Match(MySqlToken.PuncComma);
                    tempExpr2 = Expression();
                    Match(MySqlToken.PuncRightParen);
                    return new ArithmeticModExpression(tempExpr, tempExpr2).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.KwChar:
                {
                    lexer.NextToken();
                    Match(MySqlToken.PuncLeftParen);
                    return FunctionChar();
                }

                case MySqlToken.KwConvert:
                {
                    lexer.NextToken();
                    Match(MySqlToken.PuncLeftParen);
                    return FunctionConvert();
                }

                case MySqlToken.Identifier:
                {
                    tempStr = lexer.GetStringValue();
                    tempStrUp = lexer.GetStringValueUppercase();
                    lexer.NextToken();
                    return StartedFromIdentifier(tempStr, tempStrUp);
                }

                case MySqlToken.OpAsterisk:
                {
                    lexer.NextToken();
                    return new Wildcard(null).SetCacheEvalRst(cacheEvalRst);
                }

                default:
                {
                    throw Err("unrecognized token as first token of primary: " + lexer.Token());
                }
            }
        }
 public virtual void Visit(LiteralHexadecimal node)
 {
 }
        /// <summary>
        ///     last token consumed is
        ///     <see cref="MySqlToken.Identifier" />
        ///     , MUST NOT be
        ///     <code>null</code>
        /// </summary>
        /// <exception cref="System.SqlSyntaxErrorException" />
        private IExpression StartedFromIdentifier(string consumed, string consumedUp)
        {
            IExpression tempExpr;
            IExpression tempExpr2;
            IList<IExpression> tempExprList;
            string tempStr;
            StringBuilder tempSb;
            bool tempGroupDistinct;
            switch (lexer.Token())
            {
                case MySqlToken.PuncDot:
                {
                    for (tempExpr = new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                         lexer.Token() == MySqlToken.PuncDot;)
                    {
                        switch (lexer.NextToken())
                        {
                            case MySqlToken.Identifier:
                            {
                                tempExpr =
                                    new Identifier((Identifier)tempExpr, lexer.GetStringValue(),
                                        lexer.GetStringValueUppercase()).SetCacheEvalRst(cacheEvalRst);
                                lexer.NextToken();
                                break;
                            }

                            case MySqlToken.OpAsterisk:
                            {
                                lexer.NextToken();
                                return new Wildcard((Identifier)tempExpr).SetCacheEvalRst(cacheEvalRst);
                            }

                            default:
                            {
                                throw Err("expect IDENTIFIER or '*' after '.', but is " + lexer.Token());
                            }
                        }
                    }
                    return tempExpr;
                }

                case MySqlToken.LiteralBit:
                {
                    if (consumed[0] != '_')
                    {
                        return new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                    }
                    tempStr = lexer.GetStringValue();
                    lexer.NextToken();
                    return new LiteralBitField(consumed, tempStr).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralHex:
                {
                    if (consumed[0] != '_')
                    {
                        return new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                    }
                    var hex = new LiteralHexadecimal(consumed, lexer.Sql, lexer.OffsetCache, lexer.SizeCache, charset);
                    lexer.NextToken();
                    return hex.SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.LiteralChars:
                {
                    if (consumed[0] != '_')
                    {
                        return new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                    }
                    tempSb = new StringBuilder();
                    do
                    {
                        lexer.AppendStringContent(tempSb);
                    } while (lexer.NextToken() == MySqlToken.LiteralChars);
                    return new LiteralString(consumed, tempSb.ToString(), false).SetCacheEvalRst(cacheEvalRst);
                }

                case MySqlToken.PuncLeftParen:
                {
                    consumedUp = IdentifierExpr.UnescapeName(consumedUp);
                    switch (functionManager.GetParsingStrategy(consumedUp))
                    {
                        case FunctionParsingStrategy.GetFormat:
                        {
                            // GET_FORMAT({DATE|TIME|DATETIME},
                            // {'EUR'|'USA'|'JIS'|'ISO'|'INTERNAL'})
                            lexer.NextToken();
                            var gfi = MatchIdentifier("DATE", "TIME", "DATETIME", "TIMESTAMP");
                            Match(MySqlToken.PuncComma);
                            var getFormatArg = Expression();
                            Match(MySqlToken.PuncRightParen);
                            switch (gfi)
                            {
                                case 0:
                                {
                                    return new GetFormat(GetFormat.FormatType.Date, getFormatArg);
                                }

                                case 1:
                                {
                                    return new GetFormat(GetFormat.FormatType.Time, getFormatArg);
                                }

                                case 2:
                                case 3:
                                {
                                    return new GetFormat(GetFormat.FormatType.Datetime, getFormatArg);
                                }
                            }
                            throw Err("unexpected format type for GET_FORMAT()");
                        }

                        case FunctionParsingStrategy.Cast:
                        {
                            lexer.NextToken();
                            tempExpr = Expression();
                            Match(MySqlToken.KwAs);
                            var type = Type4specialFunc();
                            Match(MySqlToken.PuncRightParen);
                            var info = type.Value;
                            if (info != null)
                            {
                                return
                                    new Cast(tempExpr, type.Key, info.Key, info.Value).SetCacheEvalRst(
                                        cacheEvalRst);
                            }
                            return new Cast(tempExpr, type.Key, null, null).SetCacheEvalRst(cacheEvalRst);
                            //goto case FunctionParsingStrategy.Position;
                        }

                        case FunctionParsingStrategy.Position:
                        {
                            lexer.NextToken();
                            tempExprList = new List<IExpression>(2);
                            tempExprList.Add(Expression());
                            Match(MySqlToken.KwIn);
                            tempExprList.Add(Expression());
                            Match(MySqlToken.PuncRightParen);
                            return new Locate(tempExprList).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Substring:
                        {
                            lexer.NextToken();
                            tempExprList = new List<IExpression>(3);
                            tempExprList.Add(Expression());
                            Match(MySqlToken.PuncComma, MySqlToken.KwFrom);
                            tempExprList.Add(Expression());
                            switch (lexer.Token())
                            {
                                case MySqlToken.PuncComma:
                                case MySqlToken.KwFor:
                                {
                                    lexer.NextToken();
                                    tempExprList.Add(Expression());
                                    goto default;
                                }

                                default:
                                {
                                    Match(MySqlToken.PuncRightParen);
                                    break;
                                }
                            }
                            return new Substring(tempExprList).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Row:
                        {
                            lexer.NextToken();
                            tempExprList = ExpressionList(new List<IExpression>());
                            return new RowExpression(tempExprList).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Trim:
                        {
                            TrimDirection _trimDirection;
                            switch (lexer.NextToken())
                            {
                                case MySqlToken.KwBoth:
                                {
                                    lexer.NextToken();
                                    _trimDirection = TrimDirection.Both;
                                    break;
                                }

                                case MySqlToken.KwLeading:
                                {
                                    lexer.NextToken();
                                    _trimDirection = TrimDirection.Leading;
                                    break;
                                }

                                case MySqlToken.KwTrailing:
                                {
                                    lexer.NextToken();
                                    _trimDirection = TrimDirection.Trailing;
                                    break;
                                }

                                default:
                                {
                                    _trimDirection = TrimDirection.Default;
                                    break;
                                }
                            }
                            if (_trimDirection == TrimDirection.Default)
                            {
                                tempExpr = Expression();
                                if (lexer.Token() == MySqlToken.KwFrom)
                                {
                                    lexer.NextToken();
                                    tempExpr2 = Expression();
                                    Match(MySqlToken.PuncRightParen);
                                    return new Trim(_trimDirection, tempExpr, tempExpr2).SetCacheEvalRst(cacheEvalRst);
                                }
                                Match(MySqlToken.PuncRightParen);
                                return new Trim(_trimDirection, null, tempExpr).SetCacheEvalRst(cacheEvalRst);
                            }
                            if (lexer.Token() == MySqlToken.KwFrom)
                            {
                                lexer.NextToken();
                                tempExpr = Expression();
                                Match(MySqlToken.PuncRightParen);
                                return new Trim(_trimDirection, null, tempExpr).SetCacheEvalRst(cacheEvalRst);
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.KwFrom);
                            tempExpr2 = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Trim(_trimDirection, tempExpr, tempExpr2).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Avg:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                tempGroupDistinct = true;
                                lexer.NextToken();
                            }
                            else
                            {
                                tempGroupDistinct = false;
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Avg(tempExpr, tempGroupDistinct).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Max:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                tempGroupDistinct = true;
                                lexer.NextToken();
                            }
                            else
                            {
                                tempGroupDistinct = false;
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Max(tempExpr, tempGroupDistinct).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Min:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                tempGroupDistinct = true;
                                lexer.NextToken();
                            }
                            else
                            {
                                tempGroupDistinct = false;
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Min(tempExpr, tempGroupDistinct).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Sum:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                tempGroupDistinct = true;
                                lexer.NextToken();
                            }
                            else
                            {
                                tempGroupDistinct = false;
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Sum(tempExpr, tempGroupDistinct).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Count:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                lexer.NextToken();
                                tempExprList = ExpressionList(new List<IExpression>());
                                return new Count(tempExprList).SetCacheEvalRst(cacheEvalRst);
                            }
                            tempExpr = Expression();
                            Match(MySqlToken.PuncRightParen);
                            return new Count(tempExpr).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.GroupConcat:
                        {
                            if (lexer.NextToken() == MySqlToken.KwDistinct)
                            {
                                lexer.NextToken();
                                tempGroupDistinct = true;
                            }
                            else
                            {
                                tempGroupDistinct = false;
                            }
                            for (tempExprList = new List<IExpression>();;)
                            {
                                tempExpr = Expression();
                                tempExprList.Add(tempExpr);
                                if (lexer.Token() == MySqlToken.PuncComma)
                                {
                                    lexer.NextToken();
                                }
                                else
                                {
                                    break;
                                }
                            }
                            var isDesc = false;
                            IList<IExpression> appendedColumnNames = null;
                            tempExpr = null;
                            // order by
                            tempStr = null;
                            switch (lexer.Token())
                            {
                                case MySqlToken.KwOrder:
                                {
                                    // literalChars
                                    lexer.NextToken();
                                    Match(MySqlToken.KwBy);
                                    tempExpr = Expression();
                                    if (lexer.Token() == MySqlToken.KwAsc)
                                    {
                                        lexer.NextToken();
                                    }
                                    else
                                    {
                                        if (lexer.Token() == MySqlToken.KwDesc)
                                        {
                                            isDesc = true;
                                            lexer.NextToken();
                                        }
                                    }
                                    for (appendedColumnNames = new List<IExpression>()
                                         ;
                                         lexer.Token() == MySqlToken.PuncComma;)
                                    {
                                        lexer.NextToken();
                                        appendedColumnNames.Add(Expression());
                                    }
                                    if (lexer.Token() != MySqlToken.KwSeparator)
                                    {
                                        break;
                                    }
                                    goto case MySqlToken.KwSeparator;
                                }

                                case MySqlToken.KwSeparator:
                                {
                                    lexer.NextToken();
                                    tempSb = new StringBuilder();
                                    lexer.AppendStringContent(tempSb);
                                    tempStr = LiteralString.GetUnescapedString(tempSb.ToString());
                                    Match(MySqlToken.LiteralChars);
                                    break;
                                }
                            }
                            Match(MySqlToken.PuncRightParen);
                            return
                                new GroupConcat(tempGroupDistinct, tempExprList, tempExpr, isDesc, appendedColumnNames,
                                    tempStr).SetCacheEvalRst(cacheEvalRst);
                        }

                        case FunctionParsingStrategy.Char:
                        {
                            lexer.NextToken();
                            return FunctionChar();
                        }

                        case FunctionParsingStrategy.Convert:
                        {
                            lexer.NextToken();
                            return FunctionConvert();
                        }

                        case FunctionParsingStrategy.Extract:
                        {
                            lexer.NextToken();
                            return Extract();
                        }

                        case FunctionParsingStrategy.Timestampdiff:
                        {
                            lexer.NextToken();
                            return Timestampdiff();
                        }

                        case FunctionParsingStrategy.Timestampadd:
                        {
                            lexer.NextToken();
                            return Timestampadd();
                        }

                        case FunctionParsingStrategy.Ordinary:
                        {
                            return OrdinaryFunction(consumed, consumedUp);
                        }

                        case FunctionParsingStrategy.Default:
                        {
                            return new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                        }

                        default:
                        {
                            throw Err("unexpected function parsing strategy for id of " + consumed);
                        }
                    }
                    //goto default;
                }

                default:
                {
                    return new Identifier(null, consumed, consumedUp).SetCacheEvalRst(cacheEvalRst);
                }
            }
        }