前面已经介绍了一个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