"use strict";
/** @fileOverview Implements `class page.EBNFP.Rep extends page.EBNF.Rep`.
* @author Axel T. Schreiner <ats@cs.rit.edu>
* @version 1.5.1
*/
/** Creates a new representation of an iteration for EBNFP.
* @class Represents an iteration for EBNFP.
*
* @example
* some: item +;
* many: item *;
* optional: item ?;
*
* @private
*
* @param {epNode} _node body.
* @param {number} _min minimum number of occurences, 0 or 1.
* @param {number} _max maximum number of occurences, 1 or undefined.
*
* @property {epNode} node body.
* @property {number} min minimum number of occurences, 0 or 1.
* @property {number} max maximum number of occurences, 1 or undefined.
* @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.EBNFP.Rep = function (_node, _min, _max) {
page.EBNF.Rep.call(this, _node, _min, _max);
};
page.subclass(page.EBNFP.Rep, 'page.EBNFP.Rep', page.EBNF.Rep);
/** Called once by {@link page.EBNFP#init} to recursively translate into BNF.
*
* a+
* a*
* a?
*
* where `.min` and `.max` are `1:undefined`, `0:undefined`, or `0:1`, respectively, and are translated to
*
* $#: a $## %prec error; # .min == 1
* $##: %prec error;
* $##: $## a;
* $##: $## error;
*
* $#: $## %prec error; # if left-hand side is known
* $##: %prec error; # .min == 0
* $##: $## a;
* $##: $## error;
*
* $#: %prec error; # .min == 0, .max == 1
* $#: a;
*
* `error` depends on `_grammar.recover`
* and `%prec error` is inserted if the grammar specifies `%right error`.
*
* @private
* @override
* @variation EBNFP
*
* @param {page.EBNFP} _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.EBNFP.Rep.prototype.toBNF = function (_grammar, _nt) {
_grammar.assert('__WHERE__', !this.nt);
// insert error?
var error = _grammar.bnf.token();
var prec = 'prec' in error && error.prec.assoc == 'right';
if (!_grammar.recover && !prec) error = null;
var nt1, result = this.nt = _nt ? _nt : _grammar.bnf.nt('$'); // $#
var at = _grammar.bnf.rules.length; // placeholder
if (this.min == 0 && this.max == 1) // opt
_grammar.bnf.rules.push(null, null);
else {
if (this.min == 1 || _nt) // some or many, explicit _nt
_grammar.bnf.rules.push(null, null, null);
else // many
_grammar.bnf.rules.push(null, null);
if (error) _grammar.bnf.rules.push(null); // +error
}
var node = this.node instanceof page.BNF.T ? this.node : this.node.toBNF(_grammar);
if (this.min == 0 && this.max == 1) { // opt
_grammar.bnf.rules[at++] = // $#: [%prec error]
prec ? _grammar.bnf.rule(result, [ ], error) : _grammar.bnf.rule(result, [ ]);
_grammar.bnf.rules[at++] = _grammar.bnf.rule(result, [ node ]); // $#: node
} else {
if (this.min == 1) { // some
nt1 = _grammar.bnf.nt('$');
_grammar.bnf.rules[at++] = // $#: node $## [%prec error]
prec ? _grammar.bnf.rule(result, [ node, nt1 ], error) : _grammar.bnf.rule(result, [ node, nt1 ]);
} else if (_nt) { // many, explicit nt
nt1 = _grammar.bnf.nt('$');
_grammar.bnf.rules[at++] = // $#: $## [%prec error]
prec ? _grammar.bnf.rule(result, [ nt1 ], error) : _grammar.bnf.rule(result, [ nt1 ]);
} else // many
nt1 = result;
_grammar.bnf.rules[at++] = // $##: [%prec error]
prec ? _grammar.bnf.rule(nt1, [ ], error) : _grammar.bnf.rule(nt1, [ ]);
_grammar.bnf.rules[at++] = _grammar.bnf.rule(nt1, [ nt1, node ]); // $##: $## node
if (error)
_grammar.bnf.rules[at] = _grammar.bnf.rule(nt1, [ nt1, error ]); // $##: $## error
}
return result;
};