Source: BNF/Rule.js

"use strict";

/** @fileOverview Implements `class page.BNF.Rule`.
  * @author Axel T. Schreiner <ats@cs.rit.edu>
  * @version 1.5.0
  */

/** Creates a new BNF rule.
  * @class Represents a BNF rule.
  * @private
  *
  * @param {page.BNF.NT} _nt  left-hand side, non-terminal.
  * @param {Node[]} _symbols right-hand side.
  * 
  * @property {page.BNF.NT} nt rule's non-terminal (left-hand side).
  * @property {Node[]} symbols rule's right-hand side.
  * @property {number} index rule's index in {@link page.BNF}`.rules`,
  *   set after rule zero has been added.
  * @property {boolean} empty true if no input can be accepted.
  * @property {boolean} reached `true` if rule can be reached,
  *   transient.
  * @property {boolean} finite `true` if all non-terminals in the
  *   right-hand side have {@link page.BNF.NT}`.finite` set, transient.
  * @property {Map} first terminals at front, maps ord to {@link page.BNF.T}.
  *
  * @see page.BNF#init
  */
page.BNF.Rule = function (_nt, _symbols) {
  this.nt = _nt;
  this.symbols = _symbols;
  this.index = undefined;
  this.empty = undefined;
  this.reached = false;
  this.finite = false;
  this.first = {};
};

page.baseclass(page.BNF.Rule, 'page.BNF.Rule');

/** Displays a rule in BNF notation.
  *
  * @param {number} [_mark] precedes a symbol on the right-hand side if it is in range.
  * 
  * @returns {string}
  */
page.BNF.Rule.prototype.toString = function (_mark) {
  var result = this.nt + ': ' +
    this.symbols.map(function (symbol, n) {
      return (n == _mark ? '. ' : '') +symbol;
    }).join(' ');
    
  if (this.symbols.length == _mark) result += ' .';
  if ('precedence' in this) result += ' %prec ' + precedence;
  
  return result + ';';
};

/** Displays index, rule, `empty`, and content of `first`.
  * @returns {string}
  */
page.BNF.Rule.prototype.dump = function () {
  var result = (this.index >= 0 ? (' ' + this.index).substr(-2) + ': ' : '') + this.toString();

  if (this.empty)
    result += '\n\tempty: true';
    
  var r = '';
  for (var ord in this.first) r += ' ' + this.first[ord];
  if (r.length) result += '\n\tfirst:' + r;

  return result;
};