jscc-parser
Version:
A LALR(1) Parser Generator for JavaScript written in JavaScript.
1,171 lines (1,125 loc) • 30.3 kB
JavaScript
/*
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;
}));