"use strict"; /** @fileOverview Implements `class page.EBNFP.Lst extends page.EBNF.Lst`. * @author Axel T. Schreiner <ats@cs.rit.edu> * @version 1.5.1 */ /** Creates a new representation of a delimited iteration for EBNFP. * @class Represents a delimited iteration for EBNFP. * @extends page.EBNF.Lst * * @example * some: item +/ delimiter; * many: item ⭑/ delimiter; * * @private * * @param {epNode} _node body. * @param {epNode} _delim delimiter. * @param {number} _min minimum number of occurences, 0 or 1. * * @property {epNode} node body. * @property {epNode} delim delimiter. * @property {number} min minimum number of occurences, 0 or 1. * @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.Lst = function (_node, _delim, _min) { page.EBNF.Lst.call(this, _node, _delim, _min); }; page.subclass(page.EBNFP.Lst, 'page.EBNFP.Lst', page.EBNF.Lst); /** Called once by {@link page.EBNFP#init} to recursively translate into BNF. * * a +/ b * a ⭑/ b * * where `.min` is 1 or 0, respectively, are translated to * * $#: %prec error; # for min == 0 * $#: a $## %prec error; # factored out * $#: error $##; * $##: %prec error; * $##: $## b a; * $##: $# error a; * $##: $# b error; * $##: $# error; * * `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.Lst.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 result = this.nt = _nt ? _nt : _grammar.bnf.nt('$'); // $# var nt1 = _grammar.bnf.nt('$'); // $## var at = _grammar.bnf.rules.length; // placeholder if (this.min == 0) _grammar.bnf.rules.push(null); _grammar.bnf.rules.push(null, null, null); if (error) _grammar.bnf.rules.push(null, null, null, null); var node = this.node instanceof page.BNF.T ? this.node : this.node.toBNF(_grammar); var delim = this.delim instanceof page.BNF.T ? this.delim : this.delim.toBNF(_grammar); if (this.min == 0) _grammar.bnf.rules[at++] = // $#: [%prec error] prec ? _grammar.bnf.rule(result, [ ], error) : _grammar.bnf.rule(result, [ ]); _grammar.bnf.rules[at++] = // $#: node $## [%prec error] prec ? _grammar.bnf.rule(result, [ node, nt1 ], error) : _grammar.bnf.rule(result, [ node, nt1 ]); if (error) _grammar.bnf.rules[at++] = _grammar.bnf.rule(result, [ error, nt1 ]); // $#: error $## _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, delim, node ]); // $##: $## delim node if (error) { _grammar.bnf.rules[at++] = _grammar.bnf.rule(nt1, [ nt1, error, node ]); // $##: $## error node _grammar.bnf.rules[at++] = _grammar.bnf.rule(nt1, [ nt1, delim, error ]); // $##: $## delim error _grammar.bnf.rules[at] = _grammar.bnf.rule(nt1, [ nt1, error ]); // $##: $## error } return result; };