UNPKG

apg

Version:

(Deprecated: use apg-js instead.) An ABNF Parser Generator - generates recursive-descent parsers from grammars written in a superset of Augmented Backus-Naur Form (ABNF)

140 lines (128 loc) 5.02 kB
// This is the main or driver function for the parser generator. // It handles: // - verification and interpretation of the command line parameters // - execution of immediate commands (help, version) // - reading and verifying the input SABNF grammar file(s) // - parsing the input SABNF grammar and reporting errors, if any // - evaluation of the input grammar's attributes // - if all is OK, generating the source code for a grammar object // - writing the source to a specified file // // Note on teminology. // // APG is a parser generator. // However, it really only generates a "grammar object" (see below) from the defining SABNF grammar. // The generated parser is incomplete at this stage. // Remaining, it is the job of the user to develop the generated parser from the grammar object and the APG Library (**apg-lib**). // // The following terminology my help clear up the confusion between the idea of a "generated parser" versus a "generated grammar object". // - The generating parser: APG is an APG parser (yes, there is a circular dependence between **apg** and **apg-lib**). We'll call it the generating parser. // - The target parser: APG's goal is to generate a parser. We'll call it the target parser. // - The target grammar: this is the (ASCII) SABNF grammar defining the target parser. // - The target grammar object: APG parses the SABNF grammar and generates the JavaScript source for a target grammar object. // - The final target parser: The user then develops the final target parser using the generated target grammar // object and the APG parsing library, **apg-lib**. /* * COPYRIGHT: Copyright (c) 2017 Lowell D. Thomas, all rights reserved * LICENSE: BSD-3-Clause * AUTHOR: Lowell D. Thomas * EMAIL: lowell@coasttocoastresearch.com * WEBSITE: http://coasttocoastresearch.com/ * GITHUB: https://github.com/ldthomas/apg-js2 * NPM: https://www.npmjs.com/package/apg */ module.exports = function(args) { "use strict"; function logErrors(api, header){ console.log("\n"); console.log(header + ":"); console.log(api.errorsToAscii()); console.log("\nORIGINAL GRAMMAR:"); console.log(api.linesToAscii()); } try { debugger; var thisFileName = "apg.js: "; var fs = require("fs"); var api = require("apg-api"); var apglib = require("apg-lib"); var converter = require("apg-conv-api").converter; var getConfig = require("./command-line.js"); /* Get command line parameters and set up the configuration accordingly. */ var config = getConfig(args); if(config.error){ console.log(config.error); console.log(config.help); return } if (config.help) { console.log(config.help); return; } if (config.version) { console.log(config.version); return; } /* Get and validate the input SABNF grammar. */ api = new api(config.src); /* !!!! DEBUG !!!! */ /* test complete generation */ // api.generate(config.strict); // if (api.errors.length) { // logErrors(api, "GRAMMAR ERRORS"); // throw new Error(thisFileName + "grammar has errors"); // }else{ // fs.writeSync(config.outfd, api.toSource()); // console.log("\nJavaScript parser generated: " + config.outFilename); // } // return; /* !!!! DEBUG !!!! */ api.scan(config.strict); if (api.errors.length) { logErrors(api, "GRAMMAR CHARACTER ERRORS"); /* !!!! DEBUG !!!! */ // var html = apglib.utils.htmlToPage(api.errorsToHtml()); // fs.writeFileSync("errors.html", html); // html = apglib.utils.htmlToPage(api.linesToHtml()); // fs.writeFileSync("lines.html", html); /* !!!! DEBUG !!!! */ throw new Error(thisFileName + "invalid input grammar"); } /* parse the grammar - the syntax phase */ api.parse(config.strict); if (api.errors.length) { logErrors(api, "GRAMMAR SYNTAX ERRORS"); throw new Error(thisFileName + "grammar has syntax errors"); } /* translate the AST - the semantic phase */ api.translate(); if (api.errors.length) { logErrors(api, "GRAMMAR SEMANTIC ERRORS"); throw new Error(thisFileName + "grammar has semantic errors"); } /* attribute generation */ api.attributes(); if (api.errors.length) { logErrors(api, "GRAMMAR ATTRIBUTE ERRORS"); throw new Error(thisFileName + "grammar has semantic errors"); } /* generate a JavaScript parser */ fs.writeSync(config.outfd, api.toSource()); console.log("\nJavaScript parser generated: " + config.outFilename); } catch (e) { var msg = "EXCEPTION THROWN: "; if (e instanceof Error) { msg += e.name + ": " + e.message; } else if (typeof (e) === "string") { msg += e; } else { msg += "\n"; msg += require("util").inspect(e, { showHidden : true, depth : null, colors : true }); } console.log(msg); } }