UNPKG

jscc-parser

Version:

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

545 lines (495 loc) 27.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: printtab.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: printtab.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>/* * Universal module definition for printtab. */ (function(root, factory) { /* istanbul ignore next */ if (typeof define === 'function' &amp;&amp; define.amd) { define(['require', './global', './tabgen', './log/log', './enums/MODE_GEN', './enums/SYM', './enums/SPECIAL'], factory); } else if (typeof module === 'object' &amp;&amp; module.exports) { module.exports = factory(require); } else { root.jsccprinttab = factory(function(mod) { return root["jscc" + mod.split("/").pop()]; }); } }(this, /** * @param {reqParameter} require * @param {...*} others * @returns {jscc.printtab} */ function(require, others) { //>>excludeStart("closure", pragmas.closure); var jscc = {}; var has = (require("./localHas")); //>>excludeEnd("closure"); var log, global = /** @type {jscc.global} */ (require("./global")), tabgen = /** @type {jscc.tabgen} */ (require("./tabgen")), MODE_GEN = require("./enums/MODE_GEN"), SYM = require("./enums/SYM"), SPECIAL = require("./enums/SPECIAL"); /** * @suppress {uselessCode} */ (function() { if (has("node")) { log = /** @type {jscc.log} */ (require("./log/logNode")); } else { log = /** @type {jscc.log} */ (require("./log/log")); } })(); /** * Functions for printing parse tables. * @module {jscc.printtab} jscc/printtab * @requires module:jscc/global * @requires module:jscc/tabgen * @requires module:jscc/log/log * @requires module:jscc/enums/MODE_GEN * @requires module:jscc/enums/SYM * @requires module:jscc/enums/SPECIAL */ /** * @constructor */ jscc.printtab = function() { }; jscc.printtab.prototype = { /** * Prints the parse tables in a desired format. * @param {(jscc.enums.MODE_GEN|string)} mode - The output mode. * This can be either {@link jscc.enums.MODE_GEN.JS} to create JavaScript/ * JScript code as output or {@link jscc.enums.MODE_GEN.HTML} to create * HTML-tables as output (the HTML-tables are formatted to * look nice with the JS/CC Web Environment). * @returns {string} The code to be printed to a file or * website. * @author Jan Max Meyer * @memberof jscc.printtab */ print_parse_tables: function(mode) { var code = ""; var i, j, deepest = 0, val; switch (mode) { case MODE_GEN.HTML: case "html": code += "&lt;table class=\"print\" cellpadding=\"0\" cellspacing=\"0\">"; code += "&lt;tr>"; code += "&lt;td class=\"tabtitle\" colspan=\"2\">Pop-Table&lt;/td>"; code += "&lt;/tr>"; code += "&lt;td class=\"coltitle\" width=\"1%\" style=\"border-right: 1px solid lightgray;\">Left-hand side&lt;/td>"; code += "&lt;td class=\"coltitle\">Number of symbols to pop&lt;/td>"; code += "&lt;/tr>"; for (i = 0; i &lt; global.productions.length; i++) { code += "&lt;tr>"; code += "&lt;td style=\"border-right: 1px solid lightgray;\">" + global.productions[i].lhs + "&lt;/td>"; code += "&lt;td>" + global.productions[i].rhs.length + "&lt;/td>"; code += "&lt;/tr>"; } code += "&lt;/table>"; for (i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].kind == SYM.TERM) { deepest++; } } code += "&lt;table class=\"print\" cellpadding=\"0\" cellspacing=\"0\">"; code += "&lt;tr>"; code += "&lt;td class=\"tabtitle\" colspan=\"" + (deepest + 1) + "\">Action-Table&lt;/td>"; code += "&lt;/tr>"; code += "&lt;td class=\"coltitle\" width=\"1%\" style=\"border-right: 1px solid lightgray;\">State&lt;/td>"; for (i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].kind == SYM.TERM) { code += "&lt;td>&lt;b>" + global.symbols[i].label + "&lt;/b>&lt;/td>"; } } code += "&lt;/tr>"; for (i = 0; i &lt; global.states.length; i++) { code += "&lt;tr>"; code += "&lt;td class=\"coltitle\" style=\"border-right: 1px solid lightgray;\">" + i + "&lt;/td>"; for (j = 0; j &lt; global.symbols.length; j++) { if (global.symbols[j].kind == SYM.TERM) { code += "&lt;td>"; if ((val = tabgen.get_table_entry(global.states[i].actionrow, j)) != void(0)) { if (val &lt;= 0) { code += "r" + (val * -1); } else { code += "s" + val; } } code += "&lt;/td>"; } } code += "&lt;/tr>"; } code += "&lt;/table>"; for (i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].kind == SYM.NONTERM) { deepest++; } } code += "&lt;table class=\"print\" cellpadding=\"0\" cellspacing=\"0\">"; code += "&lt;tr>"; code += "&lt;td class=\"tabtitle\" colspan=\"" + (deepest + 1) + "\">Goto-Table&lt;/td>"; code += "&lt;/tr>"; code += "&lt;td class=\"coltitle\" width=\"1%\" style=\"border-right: 1px solid lightgray;\">State&lt;/td>"; for (i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].kind == SYM.NONTERM) { code += "&lt;td>" + global.symbols[i].label + "&lt;/td>"; } } code += "&lt;/tr>"; for (i = 0; i &lt; global.states.length; i++) { code += "&lt;tr>"; code += "&lt;td class=\"coltitle\" style=\"border-right: 1px solid lightgray;\">" + i + "&lt;/td>"; for (j = 0; j &lt; global.symbols.length; j++) { if (global.symbols[j].kind == SYM.NONTERM) { code += "&lt;td>"; if ((val = tabgen.get_table_entry(global.states[i].gotorow, j)) != void(0)) { code += val; } code += "&lt;/td>"; } } code += "&lt;/tr>"; } code += "&lt;/table>"; code += "&lt;table class=\"print\" cellpadding=\"0\" cellspacing=\"0\">"; code += "&lt;tr>"; code += "&lt;td class=\"tabtitle\" colspan=\"2\">Default Actions Table&lt;/td>"; code += "&lt;/tr>"; code += "&lt;td class=\"coltitle\" width=\"1%\" style=\"border-right: 1px solid lightgray;\">Left-hand side&lt;/td>"; code += "&lt;td class=\"coltitle\">Number of symbols to pop&lt;/td>"; code += "&lt;/tr>"; for (i = 0; i &lt; global.states.length; i++) { code += "&lt;tr>"; code += "&lt;td style=\"border-right: 1px solid lightgray;\">State " + i + "&lt;/td>"; code += "&lt;td>" + ((global.states[i].def_act &lt; 0) ? "(none)" : global.states[i].def_act) + "&lt;/td>"; code += "&lt;/tr>"; } code += "&lt;/table>"; break; case MODE_GEN.JS: case "js": var pop_tab_json = []; for (i = 0; i &lt; global.productions.length; i++) { pop_tab_json.push([global.productions[i].lhs, global.productions[i].rhs.length]); } code += "\nvar pop_tab = " + JSON.stringify(pop_tab_json) + ";\n"; var act_tab_json = []; for (i = 0; i &lt; global.states.length; i++) { var act_tab_json_item = []; for (j = 0; j &lt; global.states[i].actionrow.length; j++) { act_tab_json_item.push(global.states[i].actionrow[j].symbol, global.states[i].actionrow[j].action); } act_tab_json.push(act_tab_json_item); } code += "\n/** @type {!Array&lt;!Array&lt;number>>} */\nvar act_tab =" + JSON.stringify(act_tab_json) + ";\n"; var goto_tab_json = []; for (i = 0; i &lt; global.states.length; i++) { var goto_tab_json_item = []; for (j = 0; j &lt; global.states[i].gotorow.length; j++) { goto_tab_json_item.push(global.states[i].gotorow[j].symbol, global.states[i].gotorow[j].action); } goto_tab_json.push(goto_tab_json_item); } code += "\nvar goto_tab =" + JSON.stringify(goto_tab_json) + ";\n"; var defact_tab_json = []; for (i = 0; i &lt; global.states.length; i++) { defact_tab_json.push(global.states[i].def_act); } code += "\nvar defect_tab =" + JSON.stringify(defact_tab_json) + ";\n"; break; } return code; }, /** * * @param {Array&lt;jscc.classes.Dfa>} dfa_states * @returns {Array} * @memberof jscc.printtab */ pack_dfa: function(dfa_states) { var PL = function(line) { var out = []; while (line.length) { var first = line.shift(); var second = line.shift(); if (first == second) { out.push(first); } else { out.push([first, second]); } } return out; }; var json = []; for (var i = 0; i &lt; dfa_states.length; i++) { (function(i) { var line = []; for (var j = 0; j &lt; dfa_states[i].line.length; j++) { if (dfa_states[i].line[j] != -1) { line[j] = dfa_states[i].line[j]; } } line = PL(PL(PL(PL(PL(PL(PL(PL((line))))))))); json.push({ line: line, accept: dfa_states[i].accept }); })(i); } return json; }, /** * Generates a state-machine construction from the deterministic * finite automata. * @param {Array&lt;jscc.classes.Dfa>} dfa_states - The dfa state machine for * the lexing function. * @returns {string} The code to be inserted into the static * parser driver framework. * @author Jan Max Meyer * @memberof jscc.printtab */ print_dfa_table: function(dfa_states) { var json = [], code; for (var i = 0; i &lt; dfa_states.length; i++) { (function(i) { var line = {}; for (var j = 0; j &lt; dfa_states[i].line.length; j++) { if (dfa_states[i].line[j] != -1) { line[j] = dfa_states[i].line[j]; } } json.push({ line: line, accept: dfa_states[i].accept }); })(i); } code = JSON.stringify(this.pack_dfa(dfa_states)); // JSON quotes object keys, of course, but doing so breaks minimization. So, replace keys // with unquoted versions, when possible. return code.replace(/"([A-Za-z_][A-Za-z0-9_]*)"\s*:/g, "$1:").replace(/,/g, ",\n\t"); }, /** * Prints all symbol labels into an array; this is used for * error reporting purposes only in the resulting parser. * @returns {string} The code to be inserted into the * static parser driver framework. * @author Jan Max Meyer * @memberof jscc.printtab */ print_symbol_labels: function() { for (var i = 0, arr = []; i &lt; global.symbols.length; i++) { arr.push(global.symbols[i].label); } return "var labels = " + JSON.stringify(global.symbols) + ";\n\n"; }, /** * Prints the terminal symbol actions to be associated with a * terminal definition into a switch-case-construct. * @returns {string} The code to be inserted into the static * parser driver framework. * @author Jan Max Meyer * @memberof jscc.printtab */ print_term_actions: function() { var code = "({\n"; var re = /%match|%offset|%source/; var i, j, k; var semcode; var strmatch; for (i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].kind == SYM.TERM &amp;&amp; global.symbols[i].code != "") { code += " \"" + i + "\":"; code += " /** @suppress {uselessCode} */ function(PCB){"; semcode = ""; for (j = 0, k = 0; j &lt; global.symbols[i].code.length; j++, k++) { strmatch = re.exec(global.symbols[i].code.substr(j, global.symbols[i].code.length)); if (strmatch &amp;&amp; strmatch.index == 0) { if (strmatch[0] == "%match") { semcode += "PCB.att"; } else if (strmatch[0] == "%offset") { semcode += "( PCB.offset - PCB.att.length )"; } else if (strmatch[0] == "%source") { semcode += "PCB.src"; } j += strmatch[0].length - 1; k = semcode.length; } else { semcode += global.symbols[i].code.charAt(j); } } code += " " + semcode + "\n"; code += " return PCB.att;},\n"; } } code += "\n})"; return code; }, /** * Generates a switch-case-construction that contains all * the semantic actions. This construction should then be * generated into the static parser driver template. * @returns {string} The code to be inserted into the static * parser driver framework. * @author Jan Max Meyer * @memberof jscc.printtab */ print_actions: function() { var code = ""; var re = /%[0-9]+|%%/; var semcode, strmatch; var i, j, k, idx, src; code += "["; for (i = 0; i &lt; global.productions.length; i++) { src = global.productions[i].code; semcode = "function(){\n"; semcode += "var rval;"; for (j = 0, k = 0; j &lt; src.length; j++, k++) { strmatch = re.exec(src.substr(j, src.length)); if (strmatch &amp;&amp; strmatch.index == 0) { if (strmatch[0] == "%%") { semcode += "rval"; } else { idx = parseInt(strmatch[0].substr(1, strmatch[0].length), 10); idx = global.productions[i].rhs.length - idx; if (idx &lt; 0) { // The wildcard index is not valid. Ideally, this // condition should be caught during parsing or // semantic analysis. var badProduction = global.productions[i], badLeftSymbol = global.symbols[badProduction.lhs]; if (global.productions[i].rhs.length == 0) { // Likely, default code was used for an empty right-hand side log.error( "Default code was used for an empty right-hand side of a production, or a wildcard " + strmatch[0] + " was used explicitly. The faulty left-hand side symbol label is '" + badLeftSymbol.label + "'."); } else { log.error("The wildcard " + strmatch[0] + " was used, but there are only " + global.productions[i].rhs.length + " symbols on the right-hand side of the production. The faulty left-hand " + "side symbol label is '" + badLeftSymbol.label + "'."); } semcode += " \"\" "; } else { semcode += " arguments[" + idx + "] "; } } j += strmatch[0].length - 1; k = semcode.length; } else { semcode += src.charAt(j); } } code += " " + semcode + "\nreturn rval;},\n"; } code += "]"; return code; }, /** * Returns the value of the eof-symbol. * @returns {number} The id of the EOF-symbol. * @author Jan Max Meyer * @memberof jscc.printtab */ get_eof_symbol_id: function() { var eof_id = -1; // Find out which symbol is for EOF for (var i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].special == SPECIAL.EOF) { eof_id = i; break; } } if (eof_id == -1) { log.error("No EOF-symbol defined - This might not be possible (bug!)"); } return eof_id; }, /** * Returns the value of the error-symbol. * @returns {number} The id of the error-symbol. * @author Jan Max Meyer * @memberof jscc.printtab */ get_error_symbol_id: function() { var error_id = -1; for (var i = 0; i &lt; global.symbols.length; i++) { if (global.symbols[i].special == SPECIAL.ERROR) { error_id = i; break; } } if (error_id == -1) { log.error("No ERROR-symbol defined - This might not be possible (bug!)"); } return error_id; }, /** * Returns the ID of the whitespace-symbol. * @returns {number} The id of the whitespace-symbol. * @author Jan Max Meyer * @memberof jscc.printtab */ get_whitespace_symbol_id: function() { return global.whitespace_token; }, /** * Returns the ID of a non-existing state. * @returns {number} One greater than the length of the * states array. * @author Jan Max Meyer * @memberof jscc.printtab */ get_error_state: function() { return global.states.length + 1; } }; return new jscc.printtab(); })); </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 13:35:55 GMT-0500 (Central Daylight Time) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>