"use strict"; /** @fileOverview Implements `class page.EBNF.Alt`. * @author Axel T. Schreiner <ats@cs.rit.edu> * @version 1.5.0 */ /** Creates a new representation of a choice for EBNF. * @class Represents a choice for EBNF. * * @example * choice: a | b; * * @private * * @param {eNode[]} _nodes alternatives, at least two. * * @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.Alt = function (_nodes) { this.nodes = _nodes; this.nt = undefined; this.empty = undefined; this.first = undefined; this.follow = undefined; }; page.baseclass(page.EBNF.Alt, 'page.EBNF.Alt'); /** Displays alternatives in EBNF notation. * @returns {string} */ page.EBNF.Alt.prototype.toString = function () { return this.nodes.join(' | '); }; /** Called once by {@link page.EBNF#init} to recursively translate into BNF. * * a | b | c * * is translated to * * $#: a; * $#: b; * $#: c; * * @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.Alt.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 this.nodes.forEach(function (node) { _grammar.bnf.rules.push(null); }); // create rules this.nodes.forEach(function (node) { // $#: choice _grammar.bnf.rules[at++] = _grammar.bnf.rule(result, [ 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.Alt}`.nt` * and then delegates to the descendants. * @private */ page.EBNF.Alt.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(); }); };