UNPKG

jscc-parser

Version:

A LALR(1) Parser Generator for JavaScript written in JavaScript.

1,171 lines (1,125 loc) 30.3 kB
/* This is the general, platform-independent part of every parser driver; Input-/Output and Feature-Functions are done by the particular drivers created for the particular platform. */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' && define.amd) { define(['require', './global', './regex', './tabgen', './log/log', './classes/Production', './enums/ASSOC', './enums/SYM', './enums/SPECIAL'], factory); } else if (typeof module === 'object' && module.exports) { module.exports = factory(require); } else { root.jsccparse = factory(function(mod) { return root["jscc" + mod.split("/").pop()]; }); } }(this, /** * @param {reqParameter} require * @param {...*} others * @returns {function(string, string=):number} */ function(require, others) { var log, global = /** @type {jscc.global} */ (require("./global")), compile_regex = /** @type {function(string, number, boolean, number)} */ (require("./regex")), tabgen = /** @type {jscc.tabgen} */ (require("./tabgen")), Production = /** @type {function(new:jscc.classes.Production, ?ProductionOptions=)} */ (require("./classes/Production")), ASSOC = require("./enums/ASSOC"), SYM = require("./enums/SYM"), SPECIAL = require("./enums/SPECIAL"); //>>excludeStart("closure", pragmas.closure); var has = /** @type {hasObject} */ (require("./localHas")); //>>excludeEnd("closure"); /** * @suppress {uselessCode} */ (function() { if (has("node")) { log = /** @type {jscc.log} */ (require("./log/logNode")); } else { log = /** @type {jscc.log} */ (require("./log/log")); } })(); var first_lhs; var cur_line; //Wrapper for semantic errors function line_error( line, txt ){ log.error( "line " + line + ": " + txt ); } var __parse=(function(/** number */ eof, /** number */ whitespace, /** number */ error_token){ /// there was "continue" in code, we must to replace it var Continue = function(){throw Continue;}; /** * @template T * @param {T} value * @constructor * @extends {Error} */ var ReturnValue = function(value) { Error.call(this); this._value = value; }; ReturnValue.prototype = Object.create(Error.prototype); ReturnValue.prototype.constructor = ReturnValue; /** * @type {T} * @private */ ReturnValue.prototype._value = null; /** * @returns {T} */ ReturnValue.prototype.valueOf = function() { return this._value; }; ///can return value from any place of callback function Return(value){ throw new ReturnValue(value); } var TERMINAL_ACTIONS = (function(){ function emptyFn(PCB){return PCB.att;} var actions = ({ "13": /** @suppress {uselessCode} */ function(PCB){ return PCB.att.substr(2, PCB.att.length - 4 ); return PCB.att;}, "17": /** @suppress {uselessCode} */ function(PCB){ return Continue.apply(null, arguments); return PCB.att;}, "18": /** @suppress {uselessCode} */ function(PCB){ return Continue.apply(null, arguments); return PCB.att;}, "19": /** @suppress {uselessCode} */ function(PCB){ return Continue.apply(null, arguments); return PCB.att;}, }) return function(/** @type {!PcbClass} */ PCB, match){ try{ return (actions[match] || emptyFn)(PCB); }catch(e){ if(e instanceof ReturnValue)return e.valueOf(); if(e == Continue)return Continue; throw e; } } })(); /** * @constructor */ var DfaLex = function() { this._dfaData = [{line:[[[[[[null, [[[null, 1], [2, null]], [[null, 1], null]]], null], [[[[[1, 3], [19, 22]], [null, [4, 23]]], [null, [[null, 5], [null, 24]]]], [5, [[5, [6, 7]], [[8, 25], [9, null]]]]]], [[[[[[null, 5], 5], 5], 5], [5, [[5, [5, 26]], [null, [10, 5]]]]], [[[[[null, 5], 5], 5], 5], [5, [[5, [5, null]], [[11, null], [12, null]]]]]]], null]], accept:-1}, {line:[[[[[[null, [[[null, 1], null], [[null, 1], null]]], null], [[[[[1, null], null], null], null], null]], null], null]], accept:19}, {line:[], accept:17}, {line:[], accept:6}, {line:[], accept:10}, {line:[[[[null, [[null, [null, [[null, 5], null]]], [5, [[5, null], null]]]], [[[[[[null, 5], 5], 5], 5], [5, [[5, [5, null]], [null, [null, 5]]]]], [[[[[null, 5], 5], 5], 5], [5, [[5, [5, null]], null]]]]], null]], accept:16}, {line:[], accept:8}, {line:[], accept:7}, {line:[], accept:3}, {line:[], accept:4}, {line:[], accept:5}, {line:[], accept:9}, {line:[], accept:11}, {line:[], accept:15}, {line:[], accept:2}, {line:[], accept:14}, {line:[], accept:12}, {line:[], accept:18}, {line:[], accept:13}, {line:[[[[19, [[[[19, [13, 19]], 19], 19], 19]], [[19, [19, [19, [[27, 19], 19]]]], 19]], [19, [19, [19, [19, [19, [19, [19, null]]]]]]]]], accept:-1}, {line:[[[[19, [[[[19, [13, 19]], 19], 19], 19]], [[19, [19, [19, [[27, 19], 19]]]], 19]], [19, [19, [19, [19, [19, [19, [19, null]]]]]]]]], accept:15}, {line:[[[[23, [[[23, [23, [23, 15]]], 23], 23]], [[23, [23, [23, [[28, 23], 23]]]], 23]], [23, [23, [23, [23, [23, [23, [23, null]]]]]]]]], accept:14}, {line:[[[[null, [[[[null, [null, 14]], null], null], null]], null], null]], accept:-1}, {line:[[[[23, [[[23, [23, [23, 15]]], 23], 23]], [[23, [23, [23, [[28, 23], 23]]]], 23]], [23, [23, [23, [23, [23, [23, [23, null]]]]]]]]], accept:-1}, {line:[[[null, [null, [null, [null, [null, [null, [29, null]]]]]]], null]], accept:-1}, {line:[[[[null, [null, [null, [null, [null, [16, null]]]]]], null], null]], accept:-1}, {line:[[[[null, [[null, [[null, [37, null]], null]], null]], null], null]], accept:-1}, {line:[[[[19, [[[[19, [20, 19]], 19], 19], 19]], [[19, [19, [19, [[27, 19], 19]]]], 19]], [19, [19, [19, [19, [19, [19, [19, null]]]]]]]]], accept:-1}, {line:[[[[23, [[[23, [23, [23, 21]]], 23], 23]], [[23, [23, [23, [[28, 23], 23]]]], 23]], [23, [23, [23, [23, [23, [23, [23, null]]]]]]]]], accept:-1}, {line:[[[[38, [[38, [38, [38, [38, 30]]]], 38]], [38, [38, [38, [38, [38, [31, 38]]]]]]], [38, [38, [38, [38, [38, [38, [38, null]]]]]]]]], accept:-1}, {line:[[[[null, [[null, [null, [null, [null, 29]]]], null]], null], null]], accept:-1}, {line:[[[[29, [[29, [29, [29, [29, 17]]]], 29]], 29], [29, [29, [29, [29, [29, [29, [29, null]]]]]]]]], accept:-1}, {line:[[[[32, [[32, [[32, [33, 32]], 32]], 32]], 32], [32, [32, [32, [32, [32, [32, [32, null]]]]]]]]], accept:-1}, {line:[[[36, [[36, [36, [36, [[36, 18], 36]]]], 36]], [36, [36, [36, [36, [36, [36, [36, null]]]]]]]]], accept:-1}, {line:[[[null, [[null, [null, [null, [[null, 36], null]]]], null]], null]], accept:-1}, {line:[[[[38, [[38, [38, [38, [38, 35]]]], 38]], [38, [38, [38, [38, [38, [31, 38]]]]]]], [38, [38, [38, [38, [38, [38, [38, null]]]]]]]]], accept:-1}, {line:[[[[32, [[32, [[32, [33, 32]], 32]], 32]], [[32, [32, [32, [[32, 34], 32]]]], 32]], [32, [32, [32, [32, [32, [32, [32, null]]]]]]]]], accept:-1}, {line:[[[[32, [[32, [[32, [33, 32]], 32]], 32]], [[32, [32, [32, [[32, 34], 32]]]], 32]], [32, [32, [32, [32, [32, [32, [32, null]]]]]]]]], accept:-1}, {line:[[[[38, [[38, [38, [38, [38, 35]]]], 38]], [38, [38, [38, [38, [38, [31, 38]]]]]]], [38, [38, [38, [38, [38, [38, [38, null]]]]]]]]], accept:-1}]; }; /** * @type {!Array<!{line: !Array, accept: !number}>} * @private */ DfaLex.prototype._dfaData = []; /** * @type {number} */ DfaLex.prototype.match_pos = 0; /** * @type {?number} */ DfaLex.prototype.state = 0; /** * @type {?number} */ DfaLex.prototype.match = null; /** * @param {number} chr * @param {number} pos */ DfaLex.prototype.exec = function(chr, pos) { if (this.state !== null) { if ((typeof this.state !== "number") || this.state >= this._dfaData.length) { this.state = null; throw new Error("Invalid value for DfaLex.state at chr " + chr + " and pos " + pos); } var line = this._dfaData[this.state].line; if (typeof line === "undefined" || line === null) { var badState = this.state; this.state = null; throw new Error("At chr " + chr + " and pos " + pos + ", DfaLex._dfaData[" + badState + "] appears to exist, but its line property is " + (typeof line === "undefined" ? "undefined." : "null.")); } var p, st; for (p = 1 << 8, st = line; p; p >>= 1) { if ((chr & p) !== 0) { st = st[1]; } else { st = st[0]; } if (typeof st === "undefined") { st = null; } if (st === null)break; if (Array.isArray(st))continue; break; } var ac = this._dfaData[this.state].accept; this.state = /** @type {?number} */ (st); if (ac !== -1) { this.match = /** @type{number} */ (ac); this.match_pos = pos; } } }; var pop_tab =[[0,1],[24,5],[20,1],[23,1],[21,2],[21,1],[26,3],[26,3],[26,3],[26,2],[26,3],[27,2],[27,1],[30,3],[30,2],[22,2],[22,1],[32,4],[32,2],[33,3],[33,1],[34,3],[36,2],[36,2],[36,0],[35,1],[35,0],[37,2],[37,1],[38,1],[38,1],[38,1],[25,1],[25,2],[25,2],[25,0],[39,2],[39,1],[28,1],[28,1],[31,1],[29,1],[29,0]]; /** @type {!Array<!Array<number>>} */ var act_tab =[[12,5,13,6],[],[3,9,4,10,5,11,6,13,14,16,15,17],[],[13,18],[13,19,16,21],[],[2,23,3,9,4,10,5,11,6,13,14,16,15,17],[],[14,16,15,17],[14,16,15,17],[14,16,15,17],[7,28,14,16,15,17],[14,16,15,17],[],[16,21,12,5,13,6],[],[],[],[],[],[],[],[1,35,16,21],[7,36,14,16,15,17],[7,37,14,16,15,17],[7,38,14,16,15,17],[],[],[7,40],[],[12,5,13,6],[1,35,12,5,16,21,13,6],[],[8,45],[7,46],[],[],[],[],[],[],[],[],[],[11,54,16,21,14,16,15,17],[],[9,55,7,56],[],[10,58],[11,54,16,21,14,16,15,17],[],[],[],[],[11,54,16,21,14,16,15,17],[],[12,5,13,6],[16,21,14,16,15,17],[],[],[],[],[]]; var goto_tab =[[24,1,20,2,25,3,39,4],[],[21,7,26,8,27,12,30,14,28,15],[],[],[31,20],[],[26,22,27,12,30,14,28,15],[],[27,24,30,14,28,15],[27,25,30,14,28,15],[27,26,30,14,28,15],[30,27,28,15],[28,29],[],[25,30,31,31,39,4],[],[],[],[],[],[],[],[22,32,32,33,31,34],[30,27,28,15],[30,27,28,15],[30,27,28,15],[],[],[29,39],[],[25,41,39,4],[32,42,23,43,25,44,31,34,39,4],[],[],[],[],[],[],[],[],[],[],[],[],[33,47,34,48,35,49,37,50,38,51,31,52,28,53],[],[],[],[36,57],[38,59,31,52,28,53],[],[],[],[],[34,60,35,49,37,50,38,51,31,52,28,53],[],[25,61,39,4],[28,62,31,63],[],[],[],[],[]]; var defact_tab =[35,0,-1,2,32,-1,37,-1,5,-1,-1,-1,-1,-1,12,35,38,39,36,34,33,40,4,-1,-1,-1,-1,11,9,42,14,35,35,16,-1,-1,6,7,8,10,41,13,15,1,3,26,18,-1,20,24,25,28,29,30,31,26,17,35,-1,27,19,21,23,22]; var labels = [{"label":"def'","kind":{},"prods":[0],"nullable":0,"id":0,"code":"","level":0,"special":{},"defined":true,"first":[12,3,4,5,6,13,14,15]},{"label":"ERROR_RESYNC","kind":{},"prods":[],"nullable":false,"id":1,"code":"","level":0,"special":{},"defined":true,"first":[1]},{"label":"##","kind":{},"prods":[],"nullable":false,"id":2,"code":"","level":0,"special":{},"defined":false,"first":[2]},{"label":"<","kind":{},"prods":[],"nullable":false,"id":3,"code":"","level":0,"special":{},"defined":false,"first":[3]},{"label":">","kind":{},"prods":[],"nullable":false,"id":4,"code":"","level":0,"special":{},"defined":false,"first":[4]},{"label":"^","kind":{},"prods":[],"nullable":false,"id":5,"code":"","level":0,"special":{},"defined":false,"first":[5]},{"label":"!","kind":{},"prods":[],"nullable":false,"id":6,"code":"","level":0,"special":{},"defined":false,"first":[6]},{"label":";","kind":{},"prods":[],"nullable":false,"id":7,"code":"","level":0,"special":{},"defined":false,"first":[7]},{"label":":","kind":{},"prods":[],"nullable":false,"id":8,"code":"","level":0,"special":{},"defined":false,"first":[8]},{"label":"|","kind":{},"prods":[],"nullable":false,"id":9,"code":"","level":0,"special":{},"defined":false,"first":[9]},{"label":"&","kind":{},"prods":[],"nullable":false,"id":10,"code":"","level":0,"special":{},"defined":false,"first":[10]},{"label":"~","kind":{},"prods":[],"nullable":false,"id":11,"code":"","level":0,"special":{},"defined":false,"first":[11]},{"label":"=>","kind":{},"prods":[],"nullable":false,"id":12,"code":"","level":0,"special":{},"defined":false,"first":[12]},{"label":"CODE","kind":{},"prods":[],"nullable":false,"id":13,"code":"\treturn %match.substr(2, %match.length - 4 ); ","level":0,"special":{},"defined":false,"first":[13]},{"label":"STRING_SINGLE","kind":{},"prods":[],"nullable":false,"id":14,"code":"","level":0,"special":{},"defined":false,"first":[14]},{"label":"STRING_DOUBLE","kind":{},"prods":[],"nullable":false,"id":15,"code":"","level":0,"special":{},"defined":false,"first":[15]},{"label":"IDENT","kind":{},"prods":[],"nullable":false,"id":16,"code":"","level":0,"special":{},"defined":false,"first":[16]},{"label":"n","kind":{},"prods":[],"nullable":false,"id":17,"code":"return Continue.apply(null, arguments);","level":0,"special":{},"defined":false,"first":[17]},{"label":"/~([^~]/|~[^/]|[^~/])*~/","kind":{},"prods":[],"nullable":false,"id":18,"code":"return Continue.apply(null, arguments);","level":0,"special":{},"defined":false,"first":[18]},{"label":"[tr ]+","kind":{},"prods":[],"nullable":false,"id":19,"code":"return Continue.apply(null, arguments);","level":0,"special":{},"defined":false,"first":[19]},{"label":"header_code","kind":{},"prods":[2],"nullable":1,"id":20,"code":"","level":0,"special":{},"defined":true,"first":[12,13]},{"label":"token_assocs","kind":{},"prods":[4,5],"nullable":0,"id":21,"code":"","level":0,"special":{},"defined":true,"first":[3,4,5,6,14,15]},{"label":"grammar_defs","kind":{},"prods":[15,16],"nullable":0,"id":22,"code":"","level":0,"special":{},"defined":true,"first":[16,1]},{"label":"footer_code","kind":{},"prods":[3],"nullable":1,"id":23,"code":"","level":0,"special":{},"defined":true,"first":[12,13]},{"label":"def","kind":{},"prods":[1],"nullable":0,"id":24,"code":"","level":0,"special":{},"defined":true,"first":[12,3,4,5,6,13,14,15]},{"label":"code_opt","kind":{},"prods":[32,33,34,35],"nullable":1,"id":25,"code":"","level":0,"special":{},"defined":true,"first":[12,13]},{"label":"token_assoc","kind":{},"prods":[6,7,8,9,10],"nullable":0,"id":26,"code":"","level":0,"special":{},"defined":true,"first":[3,4,5,6,14,15]},{"label":"token_defs","kind":{},"prods":[11,12],"nullable":0,"id":27,"code":"","level":0,"special":{},"defined":true,"first":[14,15]},{"label":"string","kind":{},"prods":[38,39],"nullable":0,"id":28,"code":"","level":0,"special":{},"defined":true,"first":[14,15]},{"label":"opt_semicolon","kind":{},"prods":[41,42],"nullable":1,"id":29,"code":"","level":0,"special":{},"defined":true,"first":[7]},{"label":"token_def","kind":{},"prods":[13,14],"nullable":0,"id":30,"code":"","level":0,"special":{},"defined":true,"first":[14,15]},{"label":"identifier","kind":{},"prods":[40],"nullable":0,"id":31,"code":"","level":0,"special":{},"defined":true,"first":[16]},{"label":"grammar_def","kind":{},"prods":[17,18],"nullable":0,"id":32,"code":"","level":0,"special":{},"defined":true,"first":[16,1]},{"label":"productions","kind":{},"prods":[19,20],"nullable":1,"id":33,"code":"","level":0,"special":{},"defined":true,"first":[10,12,13,9,16,14,15,11]},{"label":"rhs","kind":{},"prods":[21],"nullable":1,"id":34,"code":"","level":0,"special":{},"defined":true,"first":[10,12,13,16,14,15,11]},{"label":"sequence_opt","kind":{},"prods":[25,26],"nullable":1,"id":35,"code":"","level":0,"special":{},"defined":true,"first":[16,14,15,11]},{"label":"rhs_prec","kind":{},"prods":[22,23,24],"nullable":1,"id":36,"code":"","level":0,"special":{},"defined":true,"first":[10]},{"label":"sequence","kind":{},"prods":[27,28],"nullable":0,"id":37,"code":"","level":0,"special":{},"defined":true,"first":[16,14,15,11]},{"label":"symbol","kind":{},"prods":[29,30,31],"nullable":0,"id":38,"code":"","level":0,"special":{},"defined":true,"first":[16,14,15,11]},{"label":"code","kind":{},"prods":[36,37],"nullable":0,"id":39,"code":"","level":0,"special":{},"defined":true,"first":[13]},{"label":"$","kind":{},"prods":[],"nullable":false,"id":40,"code":"","level":0,"special":{},"defined":false,"first":[40]}]; var ACTIONS = (function(){ var PCB = {}; var actions = [ function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval;rval = arguments[4] ; return rval;}, function(){ var rval; global.code_head += arguments[0] ; return rval;}, function(){ var rval; global.code_foot += arguments[0] ; return rval;}, function(){ var rval;rval = arguments[1] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval; global.assoc_level++; for( var i = 0; i < arguments[1] .length; i++ ){ global.symbols[ arguments[1] [i] ].level = global.assoc_level; global.symbols[ arguments[1] [i] ].assoc = ASSOC.LEFT; } return rval;}, function(){ var rval; global.assoc_level++; for( var i = 0; i < arguments[1] .length; i++ ) { global.symbols[ arguments[1] [i] ].level = global.assoc_level; global.symbols[ arguments[1] [i] ].assoc = ASSOC.RIGHT; } return rval;}, function(){ var rval; global.assoc_level++; for( var i = 0; i < arguments[1] .length; i++ ){ global.symbols[ arguments[1] [i] ].level = global.assoc_level; global.symbols[ arguments[1] [i] ].assoc = ASSOC.NOASSOC; } return rval;}, function(){ var rval;rval = arguments[1] ; return rval;}, function(){ var rval; if( global.whitespace_token == -1 ){ var regex = arguments[1] .substr( 1, arguments[1] .length - 2 ); global.whitespace_token = tabgen.create_symbol( "WHITESPACE", SYM.TERM, SPECIAL.WHITESPACE ); compile_regex( regex, global.whitespace_token, arguments[1] [0] != '\'', cur_line ); } else line_error( PCB.line, "Multiple whitespace definition" ); return rval;}, function(){ var rval; arguments[1] .push( arguments[0] ); rval = arguments[1] ; return rval;}, function(){ var rval; rval = [ arguments[0] ]; return rval;}, function(){ var rval; rval = tabgen.create_symbol( arguments[1] , SYM.TERM, SPECIAL.NONE ); var regex = arguments[2] .substr( 1, arguments[2] .length - 2 ); global.symbols[rval].code = arguments[0] ; compile_regex( regex, global.symbols[ rval ].id, arguments[2] .charAt( 0 ) != '\'', cur_line ); return rval;}, function(){ var rval; var regex = arguments[1] .substr( 1, arguments[1] .length - 2 ); rval = tabgen.create_symbol( regex.replace( /\\/g, "" ), SYM.TERM, SPECIAL.NONE ); global.symbols[rval].code = arguments[0] ; compile_regex( regex, global.symbols[ rval ].id, arguments[1] .charAt( 0 ) != '\'', cur_line ); return rval;}, function(){ var rval;rval = arguments[1] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval; var nonterm = tabgen.create_symbol( arguments[3] , SYM.NONTERM, SPECIAL.NONE ); global.symbols[nonterm].defined = true; for( var i = 0; i < arguments[1] .length; i++ ){ global.productions[ arguments[1] [i] ].lhs = nonterm; global.symbols[nonterm].prods.push( arguments[1] [i] ); } if( first_lhs ){ first_lhs = false; global.symbols[0].label = global.symbols[nonterm].label + "\'"; global.productions[0].rhs.push( nonterm ); } return rval;}, function(){ var rval;rval = arguments[1] ; return rval;}, function(){ var rval; arguments[2] .push( arguments[0] ); rval = arguments[2] ; return rval;}, function(){ var rval; rval = [ arguments[0] ]; return rval;}, function(){ var rval; var prod = new Production({ id:global.productions.length, lhs:null, rhs:/** @type {Array<number>} */ ( arguments[2] ), level:/** @type {number} */ ( arguments[1] ), code:( arguments[0] =="")?global.DEF_PROD_CODE:/** @type {string} */ ( arguments[0] ) }); //Get level of the leftmost terminal //as production level. if( prod.level == 0 ) { if( prod.rhs.length > 0 ) for( var i = prod.rhs.length-1; i >= 0; i-- ) if( global.symbols[prod.rhs[i]] && global.symbols[prod.rhs[i]].kind == SYM.TERM ) { prod.level = global.symbols[prod.rhs[i]].level; break; } } global.productions.push( prod ); rval = prod.id; return rval;}, function(){ var rval; var index; if( ( index = tabgen.find_symbol( arguments[0] , SYM.TERM, SPECIAL.NONE ) ) > -1 ) rval = global.symbols[index].level; else line_error( PCB.line, "Call to undefined terminal \"" + arguments[0] + "\"" ); return rval;}, function(){ var rval; var index; if( ( index = tabgen.find_symbol( arguments[0] .substr( 1, arguments[0] .length - 2).replace( /\\/g, "" ), SYM.TERM, SPECIAL.NONE ) ) > -1 ) rval = global.symbols[index].level; else line_error( PCB.line, "Call to undefined terminal \"" + arguments[0] + "\"" ); return rval;}, function(){ var rval; rval = 0; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval; rval = []; return rval;}, function(){ var rval; arguments[1] .push( arguments[0] ); rval = arguments[1] return rval;}, function(){ var rval; rval = [ arguments[0] ]; return rval;}, function(){ var rval; if( ( rval = tabgen.find_symbol( arguments[0] , SYM.TERM, SPECIAL.NONE ) ) <= -1 ) rval = tabgen.create_symbol( arguments[0] , SYM.NONTERM, SPECIAL.NONE ); return rval;}, function(){ var rval; if( ( rval = tabgen.find_symbol( arguments[0] .substr( 1, arguments[0] .length - 2).replace( /\\/g, "" ), SYM.TERM, SPECIAL.NONE ) ) <= -1 ) line_error( PCB.line, "Call to undefined terminal " + arguments[0] ); return rval;}, function(){ var rval; rval = tabgen.find_symbol( "ERROR_RESYNC", SYM.TERM, SPECIAL.ERROR ); return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval; rval = "return " + arguments[0] + ".apply(null, arguments);"; return rval;}, function(){ var rval; rval = "(" + arguments[0] + ").apply(null, arguments);"; return rval;}, function(){ var rval; rval = ""; return rval;}, function(){ var rval; rval = arguments[1] + arguments[0] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval;rval = arguments[0] ; return rval;}, function(){ var rval; rval = ""; return rval;}, ]; return function (/** number */ act, /** Array<*> */ vstack, /** !PcbClass */ pcb){ try{ PCB = pcb; return actions[act].apply(null,vstack); }catch(e){ if(e instanceof ReturnValue)return e.valueOf(); throw e; } } })(); /** * @param {number} top * @param {?number} la * @returns {?number} */ function get_act(top, la){ for(var i = 0; i < act_tab[top].length; i+=2) if(act_tab[top][i] === la) return act_tab[top][i+1]; return null; } function get_goto(top, pop){ for(var i = 0; i < goto_tab[top].length; i+=2) if(goto_tab[top][i] === pop) return goto_tab[top][i+1]; return null; } /** * @param {!string} src * @constructor */ var PcbClass = function(src) { this.src = src; }; /** * @type {number} */ PcbClass.prototype.line = 1; /** * @type {number} */ PcbClass.prototype.column = 1; /** * @type {number} */ PcbClass.prototype.offset = 0; /** * @type {number} */ PcbClass.prototype.error_step = 0; /** * @type {string} */ PcbClass.prototype.src = ""; /** * @type {string} */ PcbClass.prototype.att = ""; /** * @type {?number} */ PcbClass.prototype.la = null; /** * @type {?number} */ PcbClass.prototype.act = null; /** * @returns {?number} */ PcbClass.prototype.lex = function() { var /** number */ start, /** number */ pos, /** number */ chr, actionResult; var dfa = new DfaLex(); var loop = true; while(loop){ dfa.match_pos = 0; pos = this.offset + 1; do{ pos--; dfa.state = 0; dfa.match = null; start = pos; if(this.src.length <= start) { this.la = eof; return eof; } do{ chr = this.src.charCodeAt(pos); dfa.exec(chr,pos); if(dfa.state !== null) this.accountChar(chr); pos++; }while(dfa.state !== null); }while(whitespace > -1 && dfa.match === whitespace); if(dfa.match !== null){ this.att = this.src.slice(start, dfa.match_pos); this.offset = dfa.match_pos; actionResult = TERMINAL_ACTIONS(this,dfa.match); if(dfa.state !== null) this.accountChar(chr); if(actionResult === Continue) continue; this.att = actionResult; }else { this.att = ""; } loop = false; } this.la = dfa.match; return this.la; }; /** * @param {number} chr */ PcbClass.prototype.accountChar = function(chr) { if( chr === 10 ){ this.line++; this.column = 0; } this.column++; }; function parse(/** string */ src, err_off, err_la){ /** * @type {!Array<number>} */ var sstack = [0]; /** * @type {!Array<*>} */ var vstack = [0]; /** * @type {number} */ var err_cnt = 0; /** * @type {*} */ var rval; /** * @type {?number} */ var act; /** * @type {number} */ var i = 0; var PCB = new PcbClass(src); err_off = err_off || []; err_la = err_la || []; PCB.lex(); while(true){ PCB.act = get_act(sstack[0],PCB.la); if(PCB.act === null && defact_tab[sstack[0]] >= 0) PCB.act = -defact_tab[sstack[0]]; if(PCB.act === null){//Parse error? Try to recover! //Report errors only when error_step is 0, and this is not a //subsequent error from a previous parse if(PCB.error_step === 0){ err_cnt++; err_off.unshift(PCB.offset - PCB.att.length); err_la.unshift([]); for(i = 0; i < act_tab[sstack[0]].length; i+=2) err_la[0].push(labels[act_tab[sstack[0]][i]]); } //Perform error recovery while(sstack.length > 1 && PCB.act === null){ sstack.shift(); vstack.shift(); //Try to shift on error token PCB.act = get_act(sstack[0],PCB.la); if(PCB.act === error_token){ sstack.unshift(PCB.act); vstack.unshift(""); } } //Is it better to leave the parser now? if(sstack.length > 1 && PCB.act !== null){ //Ok, now try to shift on the next tokens while(PCB.la !== eof){ PCB.act = act_tab[sstack[0]][i+1]; if(PCB.act != null)break; while(PCB.lex() != null)PCB.offset++; } } if(PCB.act === null || PCB.la === eof){ break; } //Try to parse the next three tokens successfully... PCB.error_step = 3; } if(PCB.act > 0){//Shift //Parse tree generation sstack.unshift(PCB.act); vstack.unshift(PCB.att); PCB.lex(); //Successfull shift and right beyond error recovery? if(PCB.error_step > 0) PCB.error_step--; }else{ //Reduce act = -PCB.act; //vstack.unshift(vstack); rval = ACTIONS(act,vstack,PCB); //vstack.shift(); sstack.splice(0,pop_tab[act][1]); vstack.splice(0,pop_tab[act][1]); PCB.act = get_goto(sstack[0],pop_tab[act][0]); //Do some parse tree construction if desired //Goal symbol match? if(act === 0) break; //Don't use PCB.act here! //...and push it! sstack.unshift(PCB.act); vstack.unshift(rval); } } return err_cnt; } return parse; })(40,-1,1); /** * Parses the specified grammar. * @module {jscc.parse} jscc/parse * @requires module:jscc/global * @requires module:jscc/regex * @requires module:jscc/tabgen * @requires module:jscc/log/log * @param {string} str - The grammar to parse. * @param {string=} filename - The filename being parsed. Currently unused. * @returns {number} The number of parse errors. */ function parse_grammar( str, filename ){ var error_offsets = []; var error_expects = []; var parse_error = 0; first_lhs = true; cur_line = 1; //_dbg_withstepbystep = true; //_dbg_withtrace = true; if( ( parse_error += __parse( str, error_offsets, error_expects ) ) > 0 ) { for( var i = 0; i < parse_error; i++ ) line_error( ( str.substr( 0, error_offsets[i] ).match( /\n/g ) ? str.substr( 0, error_offsets[i] ).match( /\n/g ).length : 1 ), "Parse error near\n\t" + str.substr( error_offsets[i], 30 ) + ( ( error_offsets[i] + 30 < str.substr( error_offsets[i] ).length ) ? "..." : "" ) + "\n\t" + error_expects[i].join() + " expected" ); } return parse_error; } return parse_grammar; }));