/** * Created by Aleksey Chichenkov on 1/23/19. */ var js_beautify = require("./libs/js-beautifier"); var args = require("./libs/args-parser")(process.argv); var fs = require("fs"); var exec = require('child_process').exec; var config; if(args["c"] !== undefined) { config = require("./" + args["c"]); } else { config = require("./config.js"); } var inp = args["in"] ? args["in"] : config.input; var enable_logs = args["logs"] ? args["logs"] : config.logs; exec("re2c -i " + inp, function(err, stdout, stderr) { err && console.log("ERROR: ", err); err && process.exit(1); post_process_lexer(stdout); }); var post_process_lexer = function (_string) { var output = args["o"] || config.output; // replace start and end fbrackets _string = _string.replace(/START\n\{/gm, ""); _string = _string.replace(/\}\nEND/gm, ""); _string = _string.replace(/^.*(_r2c_var_.*;|unsigned int yyaccept = 0;)\n/gm, ""); // replace var yych; _string = _string.replace(/(yych = \*this._yy_cursor);\n/gm, "\tcase 1:\n yych = this._string[this._yy_cursor];\n"); // insert "case 1:" before; _string = _string.replace(/switch \(\(yych = \*this\._yy_cursor\)\) \{/gm, "this._yy_char = this._string[this._yy_cursor]; \n switch (yych) {"); // замена разыменовываний _string = _string.replace(/\*\((.*?)\);/gm, "this._string[($1)];"); // замена разыменовываний _string = _string.replace(/\*(.* ?);/gm, "this._string[$1];"); // замена разыменовываний _string = _string.replace(/\*(.* ?)\)/gm, "this._string[$1])"); // замена разыменовываний _string = _string.replace(/^yy(\d*?):/gm, "case $1:"); // replace goto marker onto case _string = _string.replace(/\) goto yy(\d*?);/gm, ") { id = $1; break; }"); // replace goto inside if _string = _string.replace(/goto yy(\d*?);/gm, "id = $1; break;"); // replace goto outside if _string = _string.replace(/\{ (addLexeme.*break;) \}/gm, "$1"); // replace addLexeme _string = _string.replace(/\{ (unknownSymbol.*break;) \}/gm, "$1"); // replace unknownSymbol _string = _string.replace(/0x00/gm, 'undefined'); // replace 0x00 _string = _string.replace(/(switch \(yych\) \{[\s\S]*?})/gm, "(function(){$1}.bind(this))(); break;"); // добавим замыкание что бы обработать свиче в свиче _string = _string.replace(/switch\((id)\)/gm, "switch(this._state)"); // replace id to this._state _string = _string.replace(/id = (\d.*?);/gm, "this._state = $1;"); // replace id = n to this._state = n _string = _string.replace(/yyaccept/gm, "this._yy_accept"); // replace yyaccept to this._yy_accept _string = _string.replace(/yych/gm, "this._yy_char"); // replace yych to this._yy_char var type = args["t"] || config.type; if(type !== undefined) { switch (type) { case "web": var wt = args["web-template"] || config["web-template"]; if(wt){ if(!fs.existsSync(wt)){ throw "Not exist file: " + wt; } var template = fs.readFileSync(wt, "utf8"); _string = template.replace(/<%%LEXER%%>/gm, _string); } else { _string = "(function () {var deps = [];define(deps, function(){\n" + _string + "return Lexer; \n});})();"; } break; case "node": _string += "\n module.exports = Lexer"; break; } } _string = process_metatags(_string); if( !(args["no-beautify"] || args["nb"] || config["no-beautify"]) ) { _string = js_beautify(_string, { indent_size: 4, indent_char: ' ', preserve_newlines: true, space_after_anon_function: true, keep_array_indentation: false, braces_on_own_line: false }); } if(!enable_logs){ _string = _string.replace(/^ *console\.log[\s\S]*?$\n/gm, ""); } fs.writeFileSync(output, _string); }; var process_metatags = function (_string) { var metatags = {}; _string = _string.replace(/&&>([A-Z_][A-Z0-9_]+)([\s\S]*?)&&/gm, function (_full, _metatag, _text) { if(!metatags[_metatag]){ metatags[_metatag] = { includes: [] }; } metatags[_metatag].includes.push(_text); return ""; }); _string = _string.replace(/&&<([A-Z_][A-Z0-9_]+)&&/gm, function (_full, _metatag) { var metatag = metatags[_metatag]; if(!metatag){ throw "not found metatag for include" } return metatag.includes.join(""); }); return _string; };