"use strict";
/** @fileOverview Implements `class page.EBNF.Seq`.
* @author Axel T. Schreiner <ats@cs.rit.edu>
* @version 1.5.0
*/
/** Creates a new representation of a sequence for EBNF.
* @class Represents a sequence for EBNF.
* @private
*
* @example
* groups: a b | c d;
*
* @param {eNode[]} _nodes sequence, at least two; null during unmarshalling.
*
* @property {eNode[]} nodes descendants, at least two.
* @property {page.BNF.NT} nt corresponding non-terminal for BNF.
* @property {boolean} empty true if no input can be accepted.
* @property {Map} first terminals at front, maps ord to {@link page.BNF.T}.
* @property {Map} follow terminals following, maps ord to {@link page.BNF.T}.
*/
page.EBNF.Seq = function (_nodes) {
this.nodes = _nodes;
this.nt = undefined;
this.empty = undefined;
this.first = undefined;
this.follow = undefined;
};
page.baseclass(page.EBNF.Seq, 'page.EBNF.Seq');
/** Displays a sequence in EBNF notation.
* @returns {string}.
*/
page.EBNF.Seq.prototype.toString = function () {
return this.nodes.map(function (node) {
return node instanceof page.EBNF.Alt || node instanceof page.EBNF.Seq ? '(' + node + ')' : node;
}).join(' ');
};
/** Called once by {@link page.EBNF#init} to recursively translate into BNF.
*
* a b
*
* is translated to
*
* $#: a b;
*
* @private
*
* @param {page.EBNF} _grammar object to which the construct belongs.
* @param {page.EBNF.NT} [_nt] left-hand side, if known; avoids the need for a fresh non-terminal.
*
* @returns {page.BNF.NT} non-terminal representing the translated construct.
*/
page.EBNF.Seq.prototype.toBNF = function (_grammar, _nt) {
_grammar.assert('__WHERE__', !this.nt);
_grammar.assert('__WHERE__', this.nodes.length > 1);
var result = this.nt = _nt ? _nt : _grammar.bnf.nt('$'); // $#
var at = _grammar.bnf.rules.length; // placeholder
_grammar.bnf.rules.push(null);
_grammar.bnf.rules[at] = _grammar.bnf.rule(result, this.nodes.map(function (node) {
return node instanceof page.BNF.T ? node : node.toBNF(_grammar);
}));
return result;
};
/** Called once by {@link page.EBNF#init} to complete EBNF grammar initialization.
* Imports {@link page.BNF.NT}`.empty`, {@link page.BNF.NT}`.first`, and
* {@link page.BNF.NT}`.follow` from {@link page.EBNF.Seq}`.nt`
* and then delegates to the descendants.
* @private
*/
page.EBNF.Seq.prototype.init = function () {
this.assert('__WHERE__', !this.first);
this.empty = this.nt.empty;
this.first = this.nt.first;
this.follow = this.nt.follow;
this.nodes.forEach(function (node) { if (node.init) node.init(); });
};