Source: parse.js

/*
	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;
}));