private static void Reduce(Stack<int> shiftReduceStack, ShiftReduce shiftReduce, Stack<IJsonValue> inputStack, Stack<ParseItem> parseStack)
        {
            var numPops = ReduceLengths[shiftReduce.Action] << 1;

            for (var i = 0; i < numPops; ++i)
                shiftReduceStack.Pop();

            var topOfStack = shiftReduceStack.Peek();
            var leftHandSide = ReduceLeftHandSides[shiftReduce.Action];

            shiftReduceStack.Push(shiftReduce.Action);
            shiftReduceStack.Push(ActionGotoTable[topOfStack, leftHandSide].Action);

            //if (Log.IsDebugEnabled)
            //    Log.Debug("Reduce r{0} by production: {1}", shiftReduce.Action, Productions[shiftReduce.Action]);

            // build the parse tree for the action at this reduction step
            ReduceAction(shiftReduce, parseStack, inputStack);
        }
        private static void ReduceAction(ShiftReduce shiftReduce, Stack<ParseItem> parseStack, Stack<IJsonValue> inputStack)
        {
            switch ((ProductionType)shiftReduce.Action)
            {
                case ProductionType.EmptyArray:
                    ReduceEmptyArray(parseStack);
                    break;

                case ProductionType.EmptyObject:
                    ReduceEmptyObject(parseStack);
                    break;

                case ProductionType.NonEmptyArray:
                    ReduceNonEmptyArray(parseStack);
                    break;

                case ProductionType.NonEmptyObject:
                    ReduceNonEmptyObject(parseStack);
                    break;

                case ProductionType.MemberMultiple:
                    ReduceMemberMultiple(parseStack);
                    break;

                case ProductionType.Object:
                    ReduceObject(parseStack);
                    break;

                case ProductionType.Array:
                    ReduceArray(parseStack);
                    break;

                case ProductionType.MemberSingle:
                    ReduceMemberSingle(parseStack);
                    break;

                case ProductionType.Pair:
                    ReducePair(inputStack, parseStack);
                    break;

                case ProductionType.ElementMultiple:
                    ReduceElementMultiple(parseStack);
                    break;

                case ProductionType.ElementSingle:
                    ReduceElementSingle(parseStack);
                    break;

                case ProductionType.ObjectValue:
                    ReduceObjectValue(parseStack);
                    break;

                case ProductionType.ArrayValue:
                    ReduceArrayValue(parseStack);
                    break;

                case ProductionType.StringValue:
                case ProductionType.NumberValue:
                case ProductionType.TrueValue:
                case ProductionType.FalseValue:
                case ProductionType.NullValue:
                    ReduceValue(inputStack, parseStack);
                    break;

                default:
                    break;
            }
        }
        private static void Shift(Stack<int> shiftReduceStack, JsonLexicalAnalyzer lex, JsonLexicalType currentLexeme, ShiftReduce shiftReduce, Stack<IJsonValue> inputStack)
        {
            shiftReduceStack.Push((int)currentLexeme);
            shiftReduceStack.Push(shiftReduce.Action);

            //if (Log.IsDebugEnabled)
            //    Log.Debug("Shift {0} s{1}", currentLexeme, shiftReduce.Action);

            switch (currentLexeme)
            {
                case JsonLexicalType.Number:
                    if (lex.CurrentDouble.HasValue)
                        inputStack.Push(new JsonNumber(lex.CurrentDouble.Value));
                    else if (lex.CurrentInt64.HasValue)
                        inputStack.Push(new JsonNumber(lex.CurrentInt64.Value));
                    break;

                case JsonLexicalType.String:
                    inputStack.Push(new JsonString(lex.CurrentString));
                    break;

                case JsonLexicalType.True:
                    inputStack.Push(new JsonBoolean(true));
                    break;

                case JsonLexicalType.False:
                    inputStack.Push(new JsonBoolean(false));
                    break;

                case JsonLexicalType.Null:
                    inputStack.Push(Singleton<JsonNull>.Instance);
                    break;

                default:
                    break;
            }
        }