lexer for NPL files. It is the same lexer of lua 5.1
        /// <summary>
        /// converting string to NPL table object 
        /// </summary>
        /// <param name="input">such as "{nid=10, name=\"value\", tab={name1=\"value1\"}}"</param>
        /// <returns>may return null if failed.</returns>
        public static NPLObjectProxy StringToNPLTable(string input)
        {
            NPLLex lex = new NPLLex();
            NPLLex.LexState ls = lex.SetInput(input);
            ls.nestlevel = 0;

            try
            {
                NPLParser.next(ls);  /* read first token */

                if(ls.t.token == '{')
                {
                    NPLObjectProxy output = new NPLObjectProxy();
                    if (DeserializePureNPLDataBlock(ls, ref output))
                    {
                        NPLParser.testnext(ls, ';');
                        if (ls.t.token == (int)NPLLex.RESERVED.TK_EOS)
                        {
                            return output;
                        }
                    }
                }
            }
            catch (Exception err)
            {
                ParaGlobal.applog("error:" + err.ToString() + "in NPLHelper::StringToNPLTable()");
                return null;
            }
            return null;
        }
        public static bool DeserializePureNPLDataBlock(NPLLex.LexState ls, ref NPLObjectProxy objProxy)
        {
            // data
            int c = ls.t.token;
            switch (c)
            {
            case (int)NPLLex.RESERVED.TK_TRUE:
                objProxy.Assign(true);
                NPLParser.next(ls);
                return true;
            case (int)NPLLex.RESERVED.TK_FALSE:
                objProxy.Assign(false);
                NPLParser.next(ls);
                return true;
            case (int)NPLLex.RESERVED.TK_NIL:
                objProxy.MakeNil();
                NPLParser.next(ls);
                return true;
            case (int)NPLLex.RESERVED.TK_NUMBER:
                objProxy.Assign(ls.t.seminfo.r);
                NPLParser.next(ls);
                return true;
            case (int)NPLLex.RESERVED.TK_STRING:
                objProxy.Assign(ls.t.seminfo.ts);
                NPLParser.next(ls);
                return true;
            case '-':
                {
                    // negative number
                    NPLParser.next(ls);
                    if(ls.t.token == (int)NPLLex.RESERVED.TK_NUMBER)
                    {
                        objProxy.Assign(- ls.t.seminfo.r);
                        NPLParser.next(ls);
                        return true;
                    }
                    else
                        return false;
                }
            case '{':
                {
                    // table object
                    NPLObjectProxy tabMsg = objProxy;

                    NPLParser.enterlevel(ls);
                    bool bBreak = false;
                    NPLParser.next(ls);
                    // auto table index that begins with 1.
                    int nTableAutoIndex = 1;
                    while (!bBreak)
                    {
                        c = ls.t.token;
                        if(c == '}')
                        {
                            // end of table
                            NPLParser.leavelevel(ls);
                            NPLParser.next(ls);
                            bBreak = true;
                        }
                        else if (c == (int)NPLLex.RESERVED.TK_NAME)
                        {
                            NPLObjectProxy proxy_ = tabMsg[ls.t.seminfo.ts];
                            // by name assignment, such as name = data|table
                            NPLParser.next(ls);
                            if(ls.t.token == '=')
                            {
                                NPLParser.next(ls);
                                if (!DeserializePureNPLDataBlock(ls, ref proxy_))
                                    return false;
                                NPLParser.testnext(ls, ',');
                            }
                            else
                                return false;
                        }
                        else if(c == '[')
                        {
                            // by integer or string key assignment, such as [number|string] = data|table
                            NPLParser.next(ls);
                            if (ls.t.token == (int)NPLLex.RESERVED.TK_NUMBER)
                            {
                                // verify that it is an integer, instead of a floating value.
                                NPLObjectProxy proxy_ = tabMsg[(int)(ls.t.seminfo.r)];

                                NPLParser.next(ls);
                                if(ls.t.token == ']')
                                {
                                    NPLParser.next(ls);
                                    if(ls.t.token == '=')
                                    {
                                        NPLParser.next(ls);
                                        if (!DeserializePureNPLDataBlock(ls, ref proxy_))
                                            return false;
                                        NPLParser.testnext(ls, ',');
                                    }
                                    else
                                        return false;
                                }
                            }
                            else if (ls.t.token == (int)NPLLex.RESERVED.TK_STRING)
                            {
                                // verify that the string is a value key(non-empty);
                                if(ls.t.seminfo.ts == string.Empty)
                                    return false;

                                NPLObjectProxy proxy_ = tabMsg[ls.t.seminfo.ts];
                                NPLParser.next(ls);
                                if(ls.t.token == ']')
                                {
                                    NPLParser.next(ls);
                                    if(ls.t.token == '=')
                                    {
                                        NPLParser.next(ls);
                                        if (!DeserializePureNPLDataBlock(ls, ref proxy_))
                                            return false;
                                        NPLParser.testnext(ls, ',');
                                    }
                                    else
                                        return false;
                                }
                            }
                            else
                                return false;
                        }
                        /// Fixed: 2008.6.3 LiXizhi
                        /// the following is for auto indexed table items {"string1", "string2\r\n", 213, nil,["A"]="B", true, false, {"another table", "field1"}}
                        else
                        {
                            NPLObjectProxy proxy_ = tabMsg[nTableAutoIndex++];
                            if( ! DeserializePureNPLDataBlock(ls, ref proxy_) )
                                return false;
                            NPLParser.testnext(ls, ',');
                        }
                    }
                    return true;
                }
            default:
                break;
            }
            return false;
        }