前端编译原理 parser.js源码解读

前面已经介绍了一个jison的使用,在正常开发中其实已经够用下,下面主要是看了下parser.js代码解读下,作为一些了解。

     下面以最简单的文法产生的parser做一些代码注释

下面是一些注释,标示了编译过程,能够了解jison产生的编译器有哪些处理

var a = (function() {
    var o = function(k, v, o, l) {
        for (o = o || {}, l = k.length; l--; o[k[l]] = v);
        return o;
    };
    var parser = {
        trace: function trace() {},
        //编译期共享对象
        yy: {},
        //标示符,$accept: 0, $end: 1,error: 2是默认的符号,E: 3, NAT: 4是分析文法获得的
        symbols_: { error: 2, E: 3, NAT: 4, $accept: 0, $end: 1 },
        //终结符
        terminals_: { 2: 'error', 4: 'NAT' },
        //对应文法规则
        productions_: [
            0,  // e` => E $end
            [
                3, //规约成符号2(E) 
                1 //堆栈移除一个状态即移除NAT,压入E
            ] // E => NAT
        ],
        //规约的时候执行的代码
        performAction: function anonymous(
            yytext,
            yyleng,
            yylineno,
            yy,
            yystate /* action[1] */,
            $$ /* vstack */,
            _$ /* lstack */
        ) {
            var $0 = $$.length - 1;
            switch (yystate) {
                case 1:
                    this.$ = $$[$0] * 1;
                    break;
            }
        },
        //移入规约自动机 lalr(1)分析表,每一值表示一个状态
        table: [
            /*状态0 I0*/{ 3: 1/**goto 遇到符号3(E),跳转到状态1 */, 4: [1, 2] /**移入,遇到符号4(NAT),移入进入状态2 */}, 
            /*状态1 I1*/{ 1: [3] /**接受 遇到符号1($end),结束程序,完成编译 */}, 
            /*状态2 I2*/{ 1: [2, 1] /**规约 遇到符号1($end),按照productions[1],进行规则 */ }
        ],
        defaultActions: { 
            2: [2, 1] //状态2进行规则规约,不用向前看符号是什么(逻辑优化)
        },
        //错误提示
        parseError: function parseError(str, hash) {
            if (hash.recoverable) {
                this.trace(str);
            } else {
                var error = new Error(str);
                error.hash = hash;
                throw error;
            }
        },
        //编译 input为处理的字符串
        parse: function parse(input) {
            var self = this,
                stack = [0],
                tstack = [],
                vstack = [null],
                lstack = [],
                table = this.table,
                yytext = '',
                yylineno = 0,
                yyleng = 0,
                recovering = 0,
                TERROR = 2,
                EOF = 1;
            var args = lstack.slice.call(arguments, 1);
            var lexer = Object.create(this.lexer);
            var sharedState = { yy: {} };
            for (var k in this.yy) {
                if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
                    sharedState.yy[k] = this.yy[k];
                }
            }
            lexer.setInput(input, sharedState.yy);
            sharedState.yy.lexer = lexer;
            sharedState.yy.parser = this;
            if (typeof lexer.yylloc === 'undefined') {
                lexer.yylloc = {};
            }
            var yyloc = lexer.yylloc;
            lstack.push(yyloc);
            //位置信息采用区间的形式显示
            var ranges = lexer.options && lexer.options.ranges;
            if (typeof sharedState.yy.parseError === 'function') {
                this.parseError = sharedState.yy.parseError;
            } else {
                this.parseError = Object.getPrototypeOf(this).parseError;
            }
            //规约的时候需要弹出堆栈
            function popStack(n) {
                //stack [0,标识符,状态,标识符,状态...],所以出栈是2倍
                stack.length = stack.length - 2 * n;
                vstack.length = vstack.length - n;
                lstack.length = lstack.length - n;
            }
            //词法分析,返回token即标示符
            var lex = function() {
                var token;
                token = lexer.lex() || EOF;
                if (typeof token !== 'number') {
                    token = self.symbols_[token] || token;
                }
                return token;
            };
            var
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值