/*
  Generated by kissy-kison.*/
KISSY.add("dom/selector/parser", function () {
    /* Generated by kison from KISSY */
    var parser = {}, S = KISSY,
        GrammarConst = {
            'SHIFT_TYPE': 1,
            'REDUCE_TYPE': 2,
            'ACCEPT_TYPE': 0,
            'TYPE_INDEX': 0,
            'PRODUCTION_INDEX': 1,
            'TO_INDEX': 2
        };
    var Lexer = function (cfg) {

        var self = this;

        /*
             lex rules.
             @type {Object[]}
             @example
             [
             {
             regexp:'\\w+',
             state:['xx'],
             token:'c',
             // this => lex
             action:function(){}
             }
             ]
             */
        self.rules = [];

        S.mix(self, cfg);

        /*
             Input languages
             @type {String}
             */

        self.resetInput(self.input);

    };
    Lexer.prototype = {
        'constructor': function (cfg) {

            var self = this;

            /*
             lex rules.
             @type {Object[]}
             @example
             [
             {
             regexp:'\\w+',
             state:['xx'],
             token:'c',
             // this => lex
             action:function(){}
             }
             ]
             */
            self.rules = [];

            S.mix(self, cfg);

            /*
             Input languages
             @type {String}
             */

            self.resetInput(self.input);

        },
        'resetInput': function (input) {
            S.mix(this, {
                input: input,
                matched: "",
                stateStack: [Lexer.STATIC.INITIAL],
                match: "",
                text: "",
                firstLine: 1,
                lineNumber: 1,
                lastLine: 1,
                firstColumn: 1,
                lastColumn: 1
            });
        },
        'getCurrentRules': function () {
            var self = this,
                currentState = self.stateStack[self.stateStack.length - 1],
                rules = [];
            currentState = self.mapState(currentState);
            S.each(self.rules, function (r) {
                var state = r.state || r[3];
                if (!state) {
                    if (currentState == Lexer.STATIC.INITIAL) {
                        rules.push(r);
                    }
                } else if (S.inArray(currentState, state)) {
                    rules.push(r);
                }
            });
            return rules;
        },
        'pushState': function (state) {
            this.stateStack.push(state);
        },
        'popState': function () {
            return this.stateStack.pop();
        },
        'getStateStack': function () {
            return this.stateStack;
        },
        'showDebugInfo': function () {
            var self = this,
                DEBUG_CONTEXT_LIMIT = Lexer.STATIC.DEBUG_CONTEXT_LIMIT,
                matched = self.matched,
                match = self.match,
                input = self.input;
            matched = matched.slice(0, matched.length - match.length);
            var past = (matched.length > DEBUG_CONTEXT_LIMIT ? "..." : "") + matched.slice(-DEBUG_CONTEXT_LIMIT).replace(/\n/, " "),
                next = match + input;
            next = next.slice(0, DEBUG_CONTEXT_LIMIT) + (next.length > DEBUG_CONTEXT_LIMIT ? "..." : "");
            return past + next + "\n" + new Array(past.length + 1).join("-") + "^";
        },
        'mapSymbol': function (t) {
            var self = this,
                symbolMap = self.symbolMap;
            if (!symbolMap) {
                return t;
            }
            return symbolMap[t] || (symbolMap[t] = (++self.symbolId));
        },
        'mapReverseSymbol': function (rs) {
            var self = this,
                symbolMap = self.symbolMap,
                i,
                reverseSymbolMap = self.reverseSymbolMap;
            if (!reverseSymbolMap && symbolMap) {
                reverseSymbolMap = self.reverseSymbolMap = {};
                for (i in symbolMap) {
                    reverseSymbolMap[symbolMap[i]] = i;
                }
            }
            if (reverseSymbolMap) {
                return reverseSymbolMap[rs];
            } else {
                return rs;
            }
        },
        'mapState': function (s) {
            var self = this,
                stateMap = self.stateMap;
            if (!stateMap) {
                return s;
            }
            return stateMap[s] || (stateMap[s] = (++self.stateId));
        },
        'lex': function () {
            var self = this,
                input = self.input,
                i,
                rule,
                m,
                ret,
                lines,
                rules = self.getCurrentRules();

            self.match = self.text = "";

            if (!input) {
                return self.mapSymbol(Lexer.STATIC.END_TAG);
            }

            for (i = 0; i < rules.length; i++) {
                rule = rules[i];
                var regexp = rule.regexp || rule[1],
                    token = rule.token || rule[0],
                    action = rule.action || rule[2] || undefined;
                if (m = input.match(regexp)) {
                    lines = m[0].match(/\n.*/g);
                    if (lines) {
                        self.lineNumber += lines.length;
                    }
                    S.mix(self, {
                        firstLine: self.lastLine,
                        lastLine: self.lineNumber + 1,
                        firstColumn: self.lastColumn,
                        lastColumn: lines ? lines[lines.length - 1].length - 1 : self.lastColumn + m[0].length
                    });
                    var match;
                    // for error report
                    match = self.match = m[0];

                    // all matches
                    self.matches = m;
                    // may change by user
                    self.text = match;
                    // matched content utils now
                    self.matched += match;
                    ret = action && action.call(self);
                    if (ret == undefined) {
                        ret = token;
                    } else {
                        ret = self.mapSymbol(ret);
                    }
                    input = input.slice(match.length);
                    self.input = input;

                    if (ret) {
                        return ret;
                    } else {
                        // ignore
                        return self.lex();
                    }
                }
            }

            S.error("lex error at line " + self.lineNumber + ":\n" + self.showDebugInfo());
            return undefined;
        }
    };
    Lexer.STATIC = {
        'INITIAL': 'I',
        'DEBUG_CONTEXT_LIMIT': 20,
        'END_TAG': '$EOF'
    };
    var lexer = new Lexer({
        'rules': [
            [2, /^\[(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [3, /^(?:[\t\r\n\f\x20]*)\]/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [4, /^(?:[\t\r\n\f\x20]*)~=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [5, /^(?:[\t\r\n\f\x20]*)\|=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [6, /^(?:[\t\r\n\f\x20]*)\^=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [7, /^(?:[\t\r\n\f\x20]*)\$=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [8, /^(?:[\t\r\n\f\x20]*)\*=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [9, /^(?:[\t\r\n\f\x20]*)\=(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [10, /^(?:(?:[\w]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))(?:[\w\d-]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))*)\(/, function () {
                this.text = KISSY.trim(this.text).slice(0, - 1);
                this.pushState('fn');
            }],
            [11, /^[^\)]*/, function () {
                this.popState();
            }, ['fn']],
            [12, /^(?:[\t\r\n\f\x20]*)\)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [13, /^:not\((?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [14, /^(?:(?:[\w]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))(?:[\w\d-]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))*)/, function () {
                this.text = this.yy.unEscape(this.text);
            }],
            [15, /^"(\\"|[^"])*"/, function () {
                this.text = this.yy.unEscapeStr(this.text);
            }],
            [15, /^'(\\'|[^'])*'/, function () {
                this.text = this.yy.unEscapeStr(this.text);
            }],
            [16, /^#(?:(?:[\w\d-]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))+)/, function () {
                this.text = this.yy.unEscape(this.text.slice(1));
            }],
            [17, /^\.(?:(?:[\w]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))(?:[\w\d-]|[^\x00-\xa0]|(?:\\[^\n\r\f0-9a-f]))*)/, function () {
                this.text = this.yy.unEscape(this.text.slice(1));
            }],
            [18, /^(?:[\t\r\n\f\x20]*),(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [19, /^::?/, 0],
            [20, /^(?:[\t\r\n\f\x20]*)\+(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [21, /^(?:[\t\r\n\f\x20]*)>(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [22, /^(?:[\t\r\n\f\x20]*)~(?:[\t\r\n\f\x20]*)/, function () {
                this.text = KISSY.trim(this.text);
            }],
            [23, /^\*/, 0],
            [24, /^(?:[\t\r\n\f\x20]+)/, 0],
            [25, /^./, 0]
        ]
    });
    parser.lexer = lexer;
    lexer.symbolMap = {
        '$EOF': 1,
        'LEFT_BRACKET': 2,
        'RIGHT_BRACKET': 3,
        'INCLUDES': 4,
        'DASH_MATCH': 5,
        'PREFIX_MATCH': 6,
        'SUFFIX_MATCH': 7,
        'SUBSTRING_MATCH': 8,
        'ALL_MATCH': 9,
        'FUNCTION': 10,
        'PARAMETER': 11,
        'RIGHT_PARENTHESES': 12,
        'NOT': 13,
        'IDENT': 14,
        'STRING': 15,
        'HASH': 16,
        'CLASS': 17,
        'COMMA': 18,
        'COLON': 19,
        'PLUS': 20,
        'GREATER': 21,
        'TILDE': 22,
        'UNIVERSAL': 23,
        'S': 24,
        'INVALID': 25,
        '$START': 26,
        'selectors_group': 27,
        'selector': 28,
        'simple_selector_sequence': 29,
        'combinator': 30,
        'type_selector': 31,
        'id_selector': 32,
        'class_selector': 33,
        'attrib_match': 34,
        'attrib': 35,
        'attrib_val': 36,
        'pseudo': 37,
        'negation': 38,
        'negation_arg': 39,
        'suffix_selector': 40,
        'suffix_selectors': 41
    };
    parser.productions = [
        [26, [27]],
        [27, [28], function () {
            return [this.$1];
        }],
        [27, [27, 18, 28], function () {
            this.$1.push(this.$3);
        }],
        [28, [29]],
        [28, [28, 30, 29], function () {
            // LinkedList

            this.$1.nextCombinator = this.$3.prevCombinator = this.$2;
            var order;
            order = this.$1.order = this.$1.order || 0;
            this.$3.order = order + 1;
            this.$3.prev = this.$1;
            this.$1.next = this.$3;
            return this.$3;
        }],
        [30, [20]],
        [30, [21]],
        [30, [22]],
        [30, [24], function () {
            return ' ';
        }],
        [31, [14], function () {
            return {
                t: 'tag',
                value: this.$1
            };
        }],
        [31, [23], function () {
            return {
                t: 'tag',
                value: this.$1
            };
        }],
        [32, [16], function () {
            return {
                t: 'id',
                value: this.$1
            };
        }],
        [33, [17], function () {
            return {
                t: 'cls',
                value: this.$1
            };
        }],
        [34, [6]],
        [34, [7]],
        [34, [8]],
        [34, [9]],
        [34, [4]],
        [34, [5]],
        [35, [2, 14, 3], function () {
            return {
                t: 'attrib',
                value: {
                    ident: this.$2
                }
            };
        }],
        [36, [14]],
        [36, [15]],
        [35, [2, 14, 34, 36, 3], function () {
            return {
                t: 'attrib',
                value: {
                    ident: this.$2,
                    match: this.$3,
                    value: this.$4
                }
            };
        }],
        [37, [19, 10, 11, 12], function () {
            return {
                t: 'pseudo',
                value: {
                    fn: this.$2.toLowerCase(),
                    param: this.$3
                }
            };
        }],
        [37, [19, 14], function () {
            return {
                t: 'pseudo',
                value: {
                    ident: this.$2.toLowerCase()
                }
            };
        }],
        [38, [13, 39, 12], function () {
            return {
                t: 'pseudo',
                value: {
                    fn: 'not',
                    param: this.$2
                }
            };
        }],
        [39, [31]],
        [39, [32]],
        [39, [33]],
        [39, [35]],
        [39, [37]],
        [40, [32]],
        [40, [33]],
        [40, [35]],
        [40, [37]],
        [40, [38]],
        [41, [40], function () {
            return [this.$1];
        }],
        [41, [41, 40], function () {
            this.$1.push(this.$2);
        }],
        [29, [31]],
        [29, [41], function () {
            return {
                suffix: this.$1
            };
        }],
        [29, [31, 41], function () {
            return {
                t: 'tag',
                value: this.$1.value,
                suffix: this.$2
            };
        }]
    ];
    parser.table = {
        'gotos': {
            '0': {
                '27': 8,
                '28': 9,
                '29': 10,
                '31': 11,
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 17,
                '41': 18
            },
            '2': {
                '31': 20,
                '32': 21,
                '33': 22,
                '35': 23,
                '37': 24,
                '39': 25
            },
            '9': {
                '30': 33
            },
            '11': {
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 17,
                '41': 34
            },
            '18': {
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 35
            },
            '19': {
                '34': 43
            },
            '28': {
                '28': 46,
                '29': 10,
                '31': 11,
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 17,
                '41': 18
            },
            '33': {
                '29': 47,
                '31': 11,
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 17,
                '41': 18
            },
            '34': {
                '32': 12,
                '33': 13,
                '35': 14,
                '37': 15,
                '38': 16,
                '40': 35
            },
            '43': {
                '36': 50
            },
            '46': {
                '30': 33
            }
        },
        'action': {
            '0': {
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '14': [1, 0, 3],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '19': [1, 0, 6],
                '23': [1, 0, 7]
            },
            '1': {
                '14': [1, 0, 19]
            },
            '2': {
                '2': [1, 0, 1],
                '14': [1, 0, 3],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '19': [1, 0, 6],
                '23': [1, 0, 7]
            },
            '3': {
                '1': [2, 9, 0],
                '2': [2, 9, 0],
                '12': [2, 9, 0],
                '13': [2, 9, 0],
                '16': [2, 9, 0],
                '17': [2, 9, 0],
                '18': [2, 9, 0],
                '19': [2, 9, 0],
                '20': [2, 9, 0],
                '21': [2, 9, 0],
                '22': [2, 9, 0],
                '24': [2, 9, 0]
            },
            '4': {
                '1': [2, 11, 0],
                '2': [2, 11, 0],
                '12': [2, 11, 0],
                '13': [2, 11, 0],
                '16': [2, 11, 0],
                '17': [2, 11, 0],
                '18': [2, 11, 0],
                '19': [2, 11, 0],
                '20': [2, 11, 0],
                '21': [2, 11, 0],
                '22': [2, 11, 0],
                '24': [2, 11, 0]
            },
            '5': {
                '1': [2, 12, 0],
                '2': [2, 12, 0],
                '12': [2, 12, 0],
                '13': [2, 12, 0],
                '16': [2, 12, 0],
                '17': [2, 12, 0],
                '18': [2, 12, 0],
                '19': [2, 12, 0],
                '20': [2, 12, 0],
                '21': [2, 12, 0],
                '22': [2, 12, 0],
                '24': [2, 12, 0]
            },
            '6': {
                '10': [1, 0, 26],
                '14': [1, 0, 27]
            },
            '7': {
                '1': [2, 10, 0],
                '2': [2, 10, 0],
                '12': [2, 10, 0],
                '13': [2, 10, 0],
                '16': [2, 10, 0],
                '17': [2, 10, 0],
                '18': [2, 10, 0],
                '19': [2, 10, 0],
                '20': [2, 10, 0],
                '21': [2, 10, 0],
                '22': [2, 10, 0],
                '24': [2, 10, 0]
            },
            '8': {
                '1': [0, 0, 0],
                '18': [1, 0, 28]
            },
            '9': {
                '1': [2, 1, 0],
                '18': [2, 1, 0],
                '20': [1, 0, 29],
                '21': [1, 0, 30],
                '22': [1, 0, 31],
                '24': [1, 0, 32]
            },
            '10': {
                '1': [2, 3, 0],
                '18': [2, 3, 0],
                '20': [2, 3, 0],
                '21': [2, 3, 0],
                '22': [2, 3, 0],
                '24': [2, 3, 0]
            },
            '11': {
                '1': [2, 38, 0],
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '18': [2, 38, 0],
                '19': [1, 0, 6],
                '20': [2, 38, 0],
                '21': [2, 38, 0],
                '22': [2, 38, 0],
                '24': [2, 38, 0]
            },
            '12': {
                '1': [2, 31, 0],
                '2': [2, 31, 0],
                '13': [2, 31, 0],
                '16': [2, 31, 0],
                '17': [2, 31, 0],
                '18': [2, 31, 0],
                '19': [2, 31, 0],
                '20': [2, 31, 0],
                '21': [2, 31, 0],
                '22': [2, 31, 0],
                '24': [2, 31, 0]
            },
            '13': {
                '1': [2, 32, 0],
                '2': [2, 32, 0],
                '13': [2, 32, 0],
                '16': [2, 32, 0],
                '17': [2, 32, 0],
                '18': [2, 32, 0],
                '19': [2, 32, 0],
                '20': [2, 32, 0],
                '21': [2, 32, 0],
                '22': [2, 32, 0],
                '24': [2, 32, 0]
            },
            '14': {
                '1': [2, 33, 0],
                '2': [2, 33, 0],
                '13': [2, 33, 0],
                '16': [2, 33, 0],
                '17': [2, 33, 0],
                '18': [2, 33, 0],
                '19': [2, 33, 0],
                '20': [2, 33, 0],
                '21': [2, 33, 0],
                '22': [2, 33, 0],
                '24': [2, 33, 0]
            },
            '15': {
                '1': [2, 34, 0],
                '2': [2, 34, 0],
                '13': [2, 34, 0],
                '16': [2, 34, 0],
                '17': [2, 34, 0],
                '18': [2, 34, 0],
                '19': [2, 34, 0],
                '20': [2, 34, 0],
                '21': [2, 34, 0],
                '22': [2, 34, 0],
                '24': [2, 34, 0]
            },
            '16': {
                '1': [2, 35, 0],
                '2': [2, 35, 0],
                '13': [2, 35, 0],
                '16': [2, 35, 0],
                '17': [2, 35, 0],
                '18': [2, 35, 0],
                '19': [2, 35, 0],
                '20': [2, 35, 0],
                '21': [2, 35, 0],
                '22': [2, 35, 0],
                '24': [2, 35, 0]
            },
            '17': {
                '1': [2, 36, 0],
                '2': [2, 36, 0],
                '13': [2, 36, 0],
                '16': [2, 36, 0],
                '17': [2, 36, 0],
                '18': [2, 36, 0],
                '19': [2, 36, 0],
                '20': [2, 36, 0],
                '21': [2, 36, 0],
                '22': [2, 36, 0],
                '24': [2, 36, 0]
            },
            '18': {
                '1': [2, 39, 0],
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '18': [2, 39, 0],
                '19': [1, 0, 6],
                '20': [2, 39, 0],
                '21': [2, 39, 0],
                '22': [2, 39, 0],
                '24': [2, 39, 0]
            },
            '19': {
                '3': [1, 0, 36],
                '4': [1, 0, 37],
                '5': [1, 0, 38],
                '6': [1, 0, 39],
                '7': [1, 0, 40],
                '8': [1, 0, 41],
                '9': [1, 0, 42]
            },
            '20': {
                '12': [2, 26, 0]
            },
            '21': {
                '12': [2, 27, 0]
            },
            '22': {
                '12': [2, 28, 0]
            },
            '23': {
                '12': [2, 29, 0]
            },
            '24': {
                '12': [2, 30, 0]
            },
            '25': {
                '12': [1, 0, 44]
            },
            '26': {
                '11': [1, 0, 45]
            },
            '27': {
                '1': [2, 24, 0],
                '2': [2, 24, 0],
                '12': [2, 24, 0],
                '13': [2, 24, 0],
                '16': [2, 24, 0],
                '17': [2, 24, 0],
                '18': [2, 24, 0],
                '19': [2, 24, 0],
                '20': [2, 24, 0],
                '21': [2, 24, 0],
                '22': [2, 24, 0],
                '24': [2, 24, 0]
            },
            '28': {
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '14': [1, 0, 3],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '19': [1, 0, 6],
                '23': [1, 0, 7]
            },
            '29': {
                '2': [2, 5, 0],
                '13': [2, 5, 0],
                '14': [2, 5, 0],
                '16': [2, 5, 0],
                '17': [2, 5, 0],
                '19': [2, 5, 0],
                '23': [2, 5, 0]
            },
            '30': {
                '2': [2, 6, 0],
                '13': [2, 6, 0],
                '14': [2, 6, 0],
                '16': [2, 6, 0],
                '17': [2, 6, 0],
                '19': [2, 6, 0],
                '23': [2, 6, 0]
            },
            '31': {
                '2': [2, 7, 0],
                '13': [2, 7, 0],
                '14': [2, 7, 0],
                '16': [2, 7, 0],
                '17': [2, 7, 0],
                '19': [2, 7, 0],
                '23': [2, 7, 0]
            },
            '32': {
                '2': [2, 8, 0],
                '13': [2, 8, 0],
                '14': [2, 8, 0],
                '16': [2, 8, 0],
                '17': [2, 8, 0],
                '19': [2, 8, 0],
                '23': [2, 8, 0]
            },
            '33': {
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '14': [1, 0, 3],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '19': [1, 0, 6],
                '23': [1, 0, 7]
            },
            '34': {
                '1': [2, 40, 0],
                '2': [1, 0, 1],
                '13': [1, 0, 2],
                '16': [1, 0, 4],
                '17': [1, 0, 5],
                '18': [2, 40, 0],
                '19': [1, 0, 6],
                '20': [2, 40, 0],
                '21': [2, 40, 0],
                '22': [2, 40, 0],
                '24': [2, 40, 0]
            },
            '35': {
                '1': [2, 37, 0],
                '2': [2, 37, 0],
                '13': [2, 37, 0],
                '16': [2, 37, 0],
                '17': [2, 37, 0],
                '18': [2, 37, 0],
                '19': [2, 37, 0],
                '20': [2, 37, 0],
                '21': [2, 37, 0],
                '22': [2, 37, 0],
                '24': [2, 37, 0]
            },
            '36': {
                '1': [2, 19, 0],
                '2': [2, 19, 0],
                '12': [2, 19, 0],
                '13': [2, 19, 0],
                '16': [2, 19, 0],
                '17': [2, 19, 0],
                '18': [2, 19, 0],
                '19': [2, 19, 0],
                '20': [2, 19, 0],
                '21': [2, 19, 0],
                '22': [2, 19, 0],
                '24': [2, 19, 0]
            },
            '37': {
                '14': [2, 17, 0],
                '15': [2, 17, 0]
            },
            '38': {
                '14': [2, 18, 0],
                '15': [2, 18, 0]
            },
            '39': {
                '14': [2, 13, 0],
                '15': [2, 13, 0]
            },
            '40': {
                '14': [2, 14, 0],
                '15': [2, 14, 0]
            },
            '41': {
                '14': [2, 15, 0],
                '15': [2, 15, 0]
            },
            '42': {
                '14': [2, 16, 0],
                '15': [2, 16, 0]
            },
            '43': {
                '14': [1, 0, 48],
                '15': [1, 0, 49]
            },
            '44': {
                '1': [2, 25, 0],
                '2': [2, 25, 0],
                '13': [2, 25, 0],
                '16': [2, 25, 0],
                '17': [2, 25, 0],
                '18': [2, 25, 0],
                '19': [2, 25, 0],
                '20': [2, 25, 0],
                '21': [2, 25, 0],
                '22': [2, 25, 0],
                '24': [2, 25, 0]
            },
            '45': {
                '12': [1, 0, 51]
            },
            '46': {
                '1': [2, 2, 0],
                '18': [2, 2, 0],
                '20': [1, 0, 29],
                '21': [1, 0, 30],
                '22': [1, 0, 31],
                '24': [1, 0, 32]
            },
            '47': {
                '1': [2, 4, 0],
                '18': [2, 4, 0],
                '20': [2, 4, 0],
                '21': [2, 4, 0],
                '22': [2, 4, 0],
                '24': [2, 4, 0]
            },
            '48': {
                '3': [2, 20, 0]
            },
            '49': {
                '3': [2, 21, 0]
            },
            '50': {
                '3': [1, 0, 52]
            },
            '51': {
                '1': [2, 23, 0],
                '2': [2, 23, 0],
                '12': [2, 23, 0],
                '13': [2, 23, 0],
                '16': [2, 23, 0],
                '17': [2, 23, 0],
                '18': [2, 23, 0],
                '19': [2, 23, 0],
                '20': [2, 23, 0],
                '21': [2, 23, 0],
                '22': [2, 23, 0],
                '24': [2, 23, 0]
            },
            '52': {
                '1': [2, 22, 0],
                '2': [2, 22, 0],
                '12': [2, 22, 0],
                '13': [2, 22, 0],
                '16': [2, 22, 0],
                '17': [2, 22, 0],
                '18': [2, 22, 0],
                '19': [2, 22, 0],
                '20': [2, 22, 0],
                '21': [2, 22, 0],
                '22': [2, 22, 0],
                '24': [2, 22, 0]
            }
        }
    };
    parser.parse = function parse(input) {

        var self = this,
            lexer = self.lexer,
            state,
            symbol,
            action,
            table = self.table,
            gotos = table.gotos,
            tableAction = table.action,
            productions = self.productions,
            valueStack = [null],
            stack = [0];

        lexer.resetInput(input);

        while (1) {
            // retrieve state number from top of stack
            state = stack[stack.length - 1];

            if (!symbol) {
                symbol = lexer.lex();
            }

            if (!symbol) {
                S.log("it is not a valid input: " + input, "error");
                return false;
            }

            // read action for current state and first input
            action = tableAction[state] && tableAction[state][symbol];

            if (!action) {
                var expected = [],
                    error;
                if (tableAction[state]) {
                    S.each(tableAction[state], function (_, symbol) {
                        expected.push(self.lexer.mapReverseSymbol(symbol));
                    });
                }
                error = "Syntax error at line " + lexer.lineNumber + ":\n" + lexer.showDebugInfo() + "\n" + "expect " + expected.join(", ");
                S.error(error);
                return false;
            }

            switch (action[GrammarConst.TYPE_INDEX]) {

            case GrammarConst.SHIFT_TYPE:

                stack.push(symbol);

                valueStack.push(lexer.text);

                // push state
                stack.push(action[GrammarConst.TO_INDEX]);

                // allow to read more
                symbol = null;

                break;

            case GrammarConst.REDUCE_TYPE:

                var production = productions[action[GrammarConst.PRODUCTION_INDEX]],
                    reducedSymbol = production.symbol || production[0],
                    reducedAction = production.action || production[2],
                    reducedRhs = production.rhs || production[1],
                    len = reducedRhs.length,
                    i = 0,
                    ret = undefined,
                    $$ = valueStack[valueStack.length - len]; // default to $$ = $1

                self.$$ = $$;

                for (; i < len; i++) {
                    self["$" + (len - i)] = valueStack[valueStack.length - 1 - i];
                }

                if (reducedAction) {
                    ret = reducedAction.call(self);
                }

                if (ret !== undefined) {
                    $$ = ret;
                } else {
                    $$ = self.$$;
                }

                if (len) {
                    stack = stack.slice(0, - 1 * len * 2);
                    valueStack = valueStack.slice(0, - 1 * len);
                }

                stack.push(reducedSymbol);

                valueStack.push($$);

                var newState = gotos[stack[stack.length - 2]][stack[stack.length - 1]];

                stack.push(newState);

                break;

            case GrammarConst.ACCEPT_TYPE:

                return $$;
            }

        }

        return undefined;

    };
    return parser;
});