UNPKG

jscc-parser

Version:

A LALR(1) Parser Generator for JavaScript written in JavaScript.

757 lines (670 loc) 35.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: tabgen.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: tabgen.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* * Universal module definition for tabgen. */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' &amp;&amp; define.amd) { define(['require', './global', './first', './util', './log/log', './classes/State', './classes/Item', './classes/TableEntry', './classes/Symbol', './enums/SPECIAL', './enums/ASSOC', './enums/SYM', './enums/MODE_GEN', './enums/EXEC', './debug'], factory); } else if (typeof module === 'object' &amp;&amp; module.exports) { module.exports = factory(require); } else { root.jscctabgen = factory(function(mod) { return root["jscc" + mod.split("/").pop()]; }); } }(this, /** * @param {reqParameter} require * @param {...*} others * @returns {jscc.tabgen} */ function(require, others) { //>>excludeStart("closure", pragmas.closure); var jscc = {}; var has = /** @type {hasObject} */ (require("./localHas")); //>>excludeEnd("closure"); var log; var global = require("./global"); var first = require("./first"); var util = require("./util"); /** * @suppress {uselessCode} */ (function() { if (has("node")) { log = require("./log/logNode"); } else { log = require("./log/log"); } })(); var State = /** @type {function(new:jscc.classes.State, StateOptions=)} */ (require("./classes/State")); var Item = /** @type {function(new:jscc.classes.Item, ItemOptions=)} */ (require("./classes/Item")); var TableEntry = /** @type {function(new:jscc.classes.TableEntry, number, number)} */ (require( "./classes/TableEntry")); var Symbol = /** @type {function(new:jscc.classes.Symbol, SymbolOptions=)} */ (require("./classes/Symbol")); var SPECIAL = require("./enums/SPECIAL"); var ASSOC = require("./enums/ASSOC"); var SYM = require("./enums/SYM"); var EXEC = require("./enums/EXEC"); var MODE_GEN = require("./enums/MODE_GEN"); var debugFunctions = require("./debug"); /** * Contains table-generation functions. * @module {jscc.tabgen} jscc/tabgen * @requires module:jscc/global * @requires module:jscc/first * @requires module:jscc/util * @requires module:jscc/log/log * @constructor */ jscc.tabgen = function() { }; /** * Creates a new {@link jscc.classes.State} object, adds it to the global states array, * and returns the new {@link jscc.classes.State} object. * @returns {!jscc.classes.State} The newly-created, default State object. */ jscc.tabgen.prototype.create_state = function() { var state = new State({ kernel: [], epsilon: [], actionrow: [], gotorow: [], done: false, closed: false, def_act: 0 }); global.states.push(state); return state; }; /** * Creates and returns a new Item instance using the specified parameter * as the {@link jscc.classes.Item#prod} value. * @param {number} p - The prod value of the new Item instance. * @returns {!jscc.classes.Item} The new Item instance. */ jscc.tabgen.prototype.create_item = function(p) { return new Item({ prod: p, dot_offset: 0, lookahead: [] }); }; /** * If row already contains a {@link jscc.classes.TableEntry} with the given symbol, * returns row. Otherwise, adds a new TableEntry with the * provided symbol and action to the row, then returns the row. * @param {Array&lt;!jscc.classes.TableEntry>} row - The row to check for the * given symbol. * @param {number} sym - The symbol for which to check, or if not found, * the symbol that becomes part of the new TableEntry. * @param {number} act - The action that becomes part of the new * TableEntry, should one be created. * @returns {!Array&lt;!jscc.classes.TableEntry>} The row parameter with the possible * addition of a new TableEntry if no TableEntry with the given symbol * was already in the row. */ jscc.tabgen.prototype.add_table_entry = function(row, sym, act) { for (var i = 0; i &lt; row.length; i++) { if (row[i].symbol == sym) { return row; } } row.push(new TableEntry(sym, act)); return row; }; /** * If row already contains a {@link jscc.classes.TableEntry} with the given symbol, * updates the {@link jscc.classes.TableEntry#action} * property of that TableEntry to match the given action. If the * symbol is not present, no changes are made to the row. Either way, * the row is returned. * @param {Array&lt;!jscc.classes.TableEntry>} row - The row to check for the given * symbol. * @param {number} sym - The symbol for which to check. * @param {number} act - The action to which to update a TableEntry * containing the given symbol. * @returns {!Array&lt;!jscc.classes.TableEntry>} The row parameter, possibly with one * modified TableEntry. */ jscc.tabgen.prototype.update_table_entry = function(row, sym, act) { var i; for (i = 0; i &lt; row.length; i++) { if (row[i].symbol == sym) { row[i].action = act; return row; } } return row; }; /** * If row contains a {@link jscc.classes.TableEntry} with the given symbol, removes that * symbol's TableEntry and returns the row. Otherwise, simply * returns the row. * @param {Array&lt;!jscc.classes.TableEntry>} row - The row to check for the given * symbol. * @param {number} sym - The symbol for which to check and, if found, * delete. * @returns {!Array&lt;!jscc.classes.TableEntry>} The row parameter, possibly with one * fewer TableEntry. */ jscc.tabgen.prototype.remove_table_entry = function(row, sym) { for (var i = 0; i &lt; row.length; i++) { if (row[i].symbol == sym) { row.splice(i, 1); return row; } } return row; }; /** * If row contains a TableEntry with the given symbol, returns that * TableEntry's {@link jscc.classes.TableEntry#action} property. * Otherwise, returns void(0). * @param {Array&lt;!jscc.classes.TableEntry>} row - The row to check for the given * symbol. * @param {number} sym - The symbol for which to check. * @returns {(number|void)} */ jscc.tabgen.prototype.get_table_entry = function(row, sym) { for (var i = 0; i &lt; row.length; i++) { if (row[i].symbol == sym) { return row[i].action; } } return void(0); }; /** * Returns the index of the first {@link jscc.global.states} * array entry whose {@link jscc.global.State#done} property * is false, or -1 if no such entry exists. * @returns {number} The index of the first undone state, or -1 if * no undone states exist. */ jscc.tabgen.prototype.get_undone_state = function() { for (var i = 0; i &lt; global.states.length; i++) { if (global.states[i].done == false) { return i; } } return -1; }; /** * Compares two {@link jscc.classes.Item} objects for * sorting purposes by comparing their * {@link jscc.classes.Item#prod} values. * @param {!jscc.classes.Item} a - The first Item * @param {!jscc.classes.Item} b - The second Item * @returns {number} Less than zero if a.prod &lt; b.prod; * greater than zero if a.prod > b.prod; zero if * a.prod equals b.prod. */ jscc.tabgen.prototype.sort_partition = function(a, b) { return a.prod - b.prod; }; /** * Returns the index within the {@link jscc.global.symbols} * array of the first symbol with the given label, SYM, and * SPECIAL values. If no such symbol is found, returns -1. * @param {string} label - The symbol label for which to search. * @param {jscc.enums.SYM} kind - Whether the symbol is terminating or * nonterminating. * @param {jscc.enums.SPECIAL=} special - The type of special symbol, if any. * Defaults to NONE. * @returns {number} - The index within the symbols array of the * first matching symbol, or -1 if there are no matching symbols. */ jscc.tabgen.prototype.find_symbol = function(label, kind, special) { if (!special) { special = SPECIAL.NONE; } for (var i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].label.toString() == label.toString() &amp;&amp; global.symbols[i].kind == kind &amp;&amp; global.symbols[i].special == special) { return i; } } return -1; }; /** * Creates a new symbol (if necessary) and appends it to the * global symbol array. If the symbol does not already exist, * the instance of that symbol is returned only. * @param {string} label - The label of the symbol. In case * of kind == SYM.NONTERM, the label is the name of the * right-hand side, else it is the regular expression for the * terminal symbol. * @param {jscc.enums.SYM} kind - Type of the symbol. This can be * SYM.NONTERM or SYM.TERM. * @param {jscc.enums.SPECIAL} special - Specialized symbols. * @returns {number} The id property of the particular Symbol * object. * @author Jan Max Meyer */ jscc.tabgen.prototype.create_symbol = function(label, kind, special) { var exists; if ((exists = this.find_symbol(label, kind, special)) > -1) { return global.symbols[exists].id; } var sym = new Symbol({ label: label, kind: kind, prods: [], nullable: false, id: global.symbols.length, code: "", associativity: ASSOC.NONE, level: 0, special: special, defined: false, first: [] }); if (kind == SYM.TERM) { sym.first.push(sym.id); } global.symbols.push(sym); return sym.id; }; /** * Checks if two item sets contain the same items. The * items may only differ in their lookahead. * @param {Array&lt;!jscc.classes.Item>} set1 - Set to be compared with * set2. * @param {Array&lt;!jscc.classes.Item>} set2 - Set to be compared with * set1. * @returns {boolean} True if equal, else false. * @author Jan Max Meyer */ jscc.tabgen.prototype.item_set_equal = function(set1, set2) { var i, j, cnt = 0; if (set1.length != set2.length) { return false; } for (i = 0; i &lt; set1.length; i++) { for (j = 0; j &lt; set2.length; j++) { if (set1[i].prod == set2[j].prod &amp;&amp; set1[i].dot_offset == set2[j].dot_offset) { cnt++; break; } } } return cnt == set1.length; }; /** * * @param {Array&lt;!jscc.classes.Item>} seed * @param {Array&lt;!jscc.classes.Item>} closure * @returns {number} * @author Jan Max Meyer */ jscc.tabgen.prototype.close_items = function(seed, closure) { var i, j, k; var cnt = 0, tmp_cnt = 0; var item; for (i = 0; i &lt; seed.length; i++) { if (seed[i].dot_offset &lt; global.productions[seed[i].prod].rhs.length) { if (global.symbols[global.productions[seed[i].prod].rhs[seed[i].dot_offset]].kind == SYM.NONTERM) { for (j = 0; j &lt; global.symbols[global.productions[seed[i].prod].rhs[seed[i].dot_offset]].prods.length; j++) { for (k = 0; k &lt; closure.length; k++) { if (closure[k].prod == global.symbols[global.productions[seed[i].prod].rhs[seed[i].dot_offset]].prods[j]) { break; } } if (k == closure.length) { item = this.create_item( global.symbols[global.productions[seed[i].prod].rhs[seed[i].dot_offset]].prods[j]); closure.push(item); cnt++; } tmp_cnt = closure[k].lookahead.length; if (first.rhs_first(closure[k], global.productions[seed[i].prod], seed[i].dot_offset + 1)) { closure[k].lookahead = util.union(closure[k].lookahead, seed[i].lookahead); } cnt += closure[k].lookahead.length - tmp_cnt; } } } } return cnt; }; /** * @summary Implements the LALR(1) closure algorithm. * @description A short overview: * 1. Closing a closure_set of Item objects from a given * kernel seed (this includes the kernel seed itself!) * 2. Moving all epsilon items to the current state's epsilon * set. * 3. Moving all symbols with the same symbol right to the * dot to a partition set. * 4. Check if there is already a state with the same items * as there are in the partition. If so, union the * lookaheads, else, create a new state and set the * partition as kernel seed. * 5. If the (probably new) state was not closed yet, perform * some table creation: If there is a terminal to the * right of the dot, do a shift on the action table, else * do a goto on the goto table. Reductions are performed * later, when all states are closed. * @param {number} s - Id of the state that should be closed. * @author Jan Max Meyer */ jscc.tabgen.prototype.lalr1_closure = function(s) { var closure = [], nclosure, partition; var partition_sym; var i, j, cnt = 0, old_cnt = 0, tmp_cnt, ns; do { old_cnt = cnt; cnt = this.close_items(((old_cnt == 0) ? global.states[s].kernel : closure), closure); } while (cnt != old_cnt); for (i = 0; i &lt; global.states[s].kernel.length; i++) { if (global.states[s].kernel[i].dot_offset &lt; global.productions[global.states[s].kernel[i].prod].rhs.length) { closure.unshift(new Item({ prod: global.states[s].kernel[i].prod, dot_offset: global.states[s].kernel[i].dot_offset, lookahead: [] })); for (j = 0; j &lt; global.states[s].kernel[i].lookahead.length; j++) { closure[0].lookahead[j] = global.states[s].kernel[i].lookahead[j]; } } } for (i = 0; i &lt; closure.length; i++) { if (global.productions[closure[i].prod].rhs.length == 0) { for (j = 0; j &lt; global.states[s].epsilon.length; j++) { if (global.states[s].epsilon[j].prod == closure[i].prod &amp;&amp; global.states[s].epsilon[j].dot_offset == closure[i].dot_offset) { break; } } if (j == global.states[s].epsilon.length) { global.states[s].epsilon.push(closure[i]); } closure.splice(i, 1); } } while (closure.length > 0) { partition = []; nclosure = []; partition_sym = -1; for (i = 0; i &lt; closure.length; i++) { if (partition.length == 0) { partition_sym = global.productions[closure[i].prod].rhs[closure[i].dot_offset]; } if (closure[i].dot_offset &lt; global.productions[closure[i].prod].rhs.length) { if (global.productions[closure[i].prod].rhs[closure[i].dot_offset] == partition_sym) { closure[i].dot_offset++; partition.push(closure[i]); } else { nclosure.push(closure[i]); } } } if (partition.length > 0) { // beachcoder Feb 23, 2009: // Uhh here was a very exciting bug that only came up on // special grammar constellations: If we don't sort the // partition set by production here, it may happen that // states get wrong lookahead, and unexpected conflicts // or failing grammars come up. partition.sort(this.sort_partition); // Now one can check for equality for (i = 0; i &lt; global.states.length; i++) { if (this.item_set_equal(global.states[i].kernel, partition)) { break; } } if (i == global.states.length) { ns = this.create_state(); ns.kernel = partition; } tmp_cnt = 0; cnt = 0; for (j = 0; j &lt; partition.length; j++) { tmp_cnt += global.states[i].kernel[j].lookahead.length; global.states[i].kernel[j].lookahead = util.union(global.states[i].kernel[j].lookahead, partition[j].lookahead); cnt += global.states[i].kernel[j].lookahead.length; } if (tmp_cnt != cnt) { global.states[i].done = false; } if (!(global.states[s].closed)) { for (j = 0; j &lt; partition.length; j++) { if (partition[j].dot_offset - 1 &lt; global.productions[partition[j].prod].rhs.length) { if (global.symbols[global.productions[partition[j].prod].rhs[partition[j].dot_offset - 1]].kind == SYM.TERM) { global.states[s].actionrow = this.add_table_entry(global.states[s].actionrow, global.productions[partition[j].prod].rhs[partition[j].dot_offset - 1], i); global.shifts++; } else { global.states[s].gotorow = this.add_table_entry(global.states[s].gotorow, global.productions[partition[j].prod].rhs[partition[j].dot_offset - 1], i); global.gotos++; } } } } } closure = nclosure; } global.states[s].closed = true; }; /** * Inserts reduce-cells into the action table. A reduction * does always occur for items with the dot to the far right * of the production and to items with no production (epsilon * items). * * The reductions are done on the corresponding lookahead * symbols. If a shift-reduce conflict appears, the function * will always behave in favor of the shift. * * Reduce-reduce conflicts are reported immediately, and need * to be solved. * @param {number} s - The index of the state where the * reductions take effect. * @author Jan Max Meyer */ jscc.tabgen.prototype.do_reductions = function(s) { var n, i, j, ex, act, output_warning, item_set; var reds = []; var max = 0, count; for (n = 0; n &lt; 2; n++) { if (!n) { item_set = global.states[s].kernel; } else { item_set = global.states[s].epsilon; } for (i = 0; i &lt; item_set.length; i++) { if (item_set[i].dot_offset == global.productions[item_set[i].prod].rhs.length) { for (j = 0; j &lt; item_set[i].lookahead.length; j++) { output_warning = true; ex = this.get_table_entry(global.states[s].actionrow, item_set[i].lookahead[j]); if (ex == void(0)) { act = -1 * item_set[i].prod; global.states[s].actionrow = this.add_table_entry(global.states[s].actionrow, item_set[i].lookahead[j], act); global.reduces++; } else { act = ex; var warning = ""; if (ex > 0) { // Shift-reduce conflict // Is there any level specified? if (global.symbols[item_set[i].lookahead[j]].level > 0 || global.productions[item_set[i].prod].level > 0) { // Is the level the same? if (global.symbols[item_set[i].lookahead[j]].level == global.productions[item_set[i].prod].level) { // In case of left-associativity, reduce if (global.symbols[item_set[i].lookahead[j]].associativity == ASSOC.LEFT) { // Reduce act = -1 * item_set[i].prod; } else if (global.symbols[item_set[i].lookahead[j]].associativity == ASSOC.NOASSOC) { // else, if nonassociativity is set, // remove table entry this.remove_table_entry(global.states[s].actionrow, item_set[i].lookahead[j]); log.warn("Removing nonassociative symbol '" + global.symbols[item_set[i].lookahead[j]].label + "' in state " + s); output_warning = false; } } else { // If symbol precedence is lower production's // precedence, reduce if (global.symbols[item_set[i].lookahead[j]].level &lt; global.productions[item_set[i].prod].level) { // Reduce act = -1 * item_set[i].prod; } } } warning = "Shift"; } else { // Reduce-reduce conflict act = ((act * -1 &lt; item_set[i].prod) ? act : -1 * item_set[i].prod); warning = "Reduce"; } warning += "-reduce conflict on symbol '" + global.symbols[item_set[i].lookahead[j]].label + "' in state " + s; warning += "\n Conflict resolved by " + ((act &lt;= 0) ? "reducing with production" : "shifting to state") + " " + ((act &lt;= 0) ? act * -1 : act); if (output_warning) { log.warn(warning); } if (act != ex) { this.update_table_entry(global.states[s].actionrow, item_set[i].lookahead[j], act); } } } } } } // Find most common reduction global.states[s].def_act = -1; // Define no default action // Are there any reductions? Then select the best of them. for (i = 0; i &lt; reds.length; i++) { for (j = 0, count = 0; j &lt; reds.length; j++) { if (reds[j] == reds[i]) { count++; } } if (max &lt; count) { max = count; global.states[s].def_act = reds[i]; } } // Remove all default reduce action reductions, if they exist. if (global.states[s].def_act >= 0) { do { count = global.states[s].actionrow.length; for (i = 0; i &lt; global.states[s].actionrow.length; i++) { if (global.states[s].actionrow[i][1] == global.states[s].def_act * -1) { global.states[s].actionrow.splice(i, 1); } } } while (count != global.states[s].actionrow.length); } }; /** * Entry function to perform table generation. If all states * of the parsing state machine are constructed, all reduce * operations are inserted in the particular positions of the * action table. * * If there is a Shift-reduce conflict, the shift takes the * higher precedence. Reduce-reduce conflicts are resolved by * choosing the first defined production. * @param {boolean} debug - Toggle debug trace output. This * should only be switched on when JS/CC is executed in a web * environment, because HTML-code will be printed. * @author Jan Max Meyer */ jscc.tabgen.prototype.lalr1_parse_table = function(debug) { var i, item, s; // Create EOF symbol item = this.create_item(0); s = this.create_symbol("$", SYM.TERM, SPECIAL.EOF); item.lookahead.push(s); // Create first state s = this.create_state(); s.kernel.push(item); while ((i = this.get_undone_state()) >= 0) { global.states[i].done = true; this.lalr1_closure(i); } for (i = 0; i &lt; global.states.length; i++) { this.do_reductions(i); } if (debug) { for (i = 0; i &lt; global.states.length; i++) { debugFunctions.print_item_set((global.exec_mode == EXEC.CONSOLE) ? MODE_GEN.TEXT : MODE_GEN.HTML, "states[" + i + "].kernel", global.states[i].kernel); debugFunctions.print_item_set((global.exec_mode == EXEC.CONSOLE) ? MODE_GEN.TEXT : MODE_GEN.HTML, "states[" + i + "].epsilon", global.states[i].epsilon); } log.debug(global.states.length + " States created."); } }; return new jscc.tabgen(); })); </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-jscc.html">jscc</a></li><li><a href="module-jscc_bitset_BitSet32.html">jscc/bitset/BitSet32</a></li><li><a href="module-jscc_bitset_BitSetBool.html">jscc/bitset/BitSetBool</a></li><li><a href="module-jscc_bitset_BitSetJava.html">jscc/bitset/BitSetJava</a></li><li><a href="module-jscc_classes_Dfa.html">jscc/classes/Dfa</a></li><li><a href="module-jscc_classes_Item.html">jscc/classes/Item</a></li><li><a href="module-jscc_classes_Nfa.html">jscc/classes/Nfa</a></li><li><a href="module-jscc_classes_Param.html">jscc/classes/Param</a></li><li><a href="module-jscc_classes_Production.html">jscc/classes/Production</a></li><li><a href="module-jscc_classes_State.html">jscc/classes/State</a></li><li><a href="module-jscc_classes_Symbol.html">jscc/classes/Symbol</a></li><li><a href="module-jscc_classes_TableEntry.html">jscc/classes/TableEntry</a></li><li><a href="module-jscc_enums_ASSOC.html">jscc/enums/ASSOC</a></li><li><a href="module-jscc_enums_EDGE.html">jscc/enums/EDGE</a></li><li><a href="module-jscc_enums_EXEC.html">jscc/enums/EXEC</a></li><li><a href="module-jscc_enums_LOG_LEVEL.html">jscc/enums/LOG_LEVEL</a></li><li><a href="module-jscc_enums_MODE_GEN.html">jscc/enums/MODE_GEN</a></li><li><a href="module-jscc_enums_SPECIAL.html">jscc/enums/SPECIAL</a></li><li><a href="module-jscc_enums_SYM.html">jscc/enums/SYM</a></li><li><a href="module-jscc_first.html">jscc/first</a></li><li><a href="module-jscc_global.html">jscc/global</a></li><li><a href="module-jscc_integrity.html">jscc/integrity</a></li><li><a href="module-jscc_io_io.html">jscc/io/io</a></li><li><a href="module-jscc_lexdbg.html">jscc/lexdbg</a></li><li><a href="module-jscc_lexdfa.html">jscc/lexdfa</a></li><li><a href="module-jscc_log_log.html">jscc/log/log</a></li><li><a href="module-jscc_parse.html">jscc/parse</a></li><li><a href="module-jscc_printtab.html">jscc/printtab</a></li><li><a href="module-jscc_regex.html">jscc/regex</a></li><li><a href="module-jscc_util.html">jscc/util</a></li></ul><h3>Classes</h3><ul><li><a href="-_anonymous_-jscc.BitSet32.html">BitSet32</a></li><li><a href="-_anonymous_-jscc.BitSetBool.html">BitSetBool</a></li><li><a href="-_anonymous_-jscc.BitSetJava.html">BitSetJava</a></li><li><a href="-_anonymous_-jscc.classes.Dfa.html">classes.Dfa</a></li><li><a href="-_anonymous_-jscc.first.html">first</a></li><li><a href="-_anonymous_-jscc.global.html">global</a></li><li><a href="-_anonymous_-jscc.integrity.html">integrity</a></li><li><a href="-_anonymous_-jscc.ioBrowser.html">ioBrowser</a></li><li><a href="-_anonymous_-jscc.ioNashorn.html">ioNashorn</a></li><li><a href="-_anonymous_-jscc.ioNode.html">ioNode</a></li><li><a href="-_anonymous_-jscc.ioRhino.html">ioRhino</a></li><li><a href="-_anonymous_-jscc.lexdbg.html">lexdbg</a></li><li><a href="-_anonymous_-jscc.lexdfa.html">lexdfa</a></li><li><a href="-_anonymous_-jscc.logBrowser.html">logBrowser</a></li><li><a href="-_anonymous_-jscc.logJava.html">logJava</a></li><li><a href="-_anonymous_-jscc.logNode.html">logNode</a></li><li><a href="-_anonymous_-jscc.printtab.html">printtab</a></li><li><a href="-_anonymous_-jscc.util.html">util</a></li><li><a href="jscc_debug.html">jscc/debug</a></li><li><a href="jscc_nfaStates.html">jscc/nfaStates</a></li><li><a href="jscc_tabgen.html">jscc/tabgen</a></li><li><a href="%257Bjscc.classes%257D.jscc.classes.State.html">jscc.classes.State</a></li></ul><h3>Namespaces</h3><ul><li><a href="jscc.debug.html">debug</a></li></ul><h3>Interfaces</h3><ul><li><a href="jscc.bitset.html">bitset</a></li><li><a href="jscc.io.html">io</a></li><li><a href="jscc.log.html">log</a></li></ul><h3><a href="global.html">Global</a></h3> </nav> <br class="clear"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Mon Aug 01 2016 11:09:19 GMT-0500 (Central Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>