245 lines
9.1 KiB
JavaScript
245 lines
9.1 KiB
JavaScript
|
(function(root, factory) {
|
||
|
if (typeof module === 'object' && module.exports) {
|
||
|
module.exports = factory(require('./nearley'));
|
||
|
} else {
|
||
|
root.generate = factory(root.nearley);
|
||
|
}
|
||
|
}(this, function(nearley) {
|
||
|
|
||
|
function serializeRules(rules, builtinPostprocessors, extraIndent) {
|
||
|
if (extraIndent == null) {
|
||
|
extraIndent = ''
|
||
|
}
|
||
|
|
||
|
return '[\n ' + rules.map(function(rule) {
|
||
|
return serializeRule(rule, builtinPostprocessors);
|
||
|
}).join(',\n ') + '\n' + extraIndent + ']';
|
||
|
}
|
||
|
|
||
|
function dedentFunc(func) {
|
||
|
var lines = func.toString().split(/\n/);
|
||
|
|
||
|
if (lines.length === 1) {
|
||
|
return [lines[0].replace(/^\s+|\s+$/g, '')];
|
||
|
}
|
||
|
|
||
|
var indent = null;
|
||
|
var tail = lines.slice(1);
|
||
|
for (var i = 0; i < tail.length; i++) {
|
||
|
var match = /^\s*/.exec(tail[i]);
|
||
|
if (match && match[0].length !== tail[i].length) {
|
||
|
if (indent === null ||
|
||
|
match[0].length < indent.length) {
|
||
|
indent = match[0];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (indent === null) {
|
||
|
return lines;
|
||
|
}
|
||
|
|
||
|
return lines.map(function dedent(line) {
|
||
|
if (line.slice(0, indent.length) === indent) {
|
||
|
return line.slice(indent.length);
|
||
|
}
|
||
|
return line;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function tabulateString(string, indent, options) {
|
||
|
var lines;
|
||
|
if(Array.isArray(string)) {
|
||
|
lines = string;
|
||
|
} else {
|
||
|
lines = string.toString().split('\n');
|
||
|
}
|
||
|
|
||
|
options = options || {};
|
||
|
var tabulated = lines.map(function addIndent(line, i) {
|
||
|
var shouldIndent = true;
|
||
|
|
||
|
if(i == 0 && !options.indentFirst) {
|
||
|
shouldIndent = false;
|
||
|
}
|
||
|
|
||
|
if(shouldIndent) {
|
||
|
return indent + line;
|
||
|
} else {
|
||
|
return line;
|
||
|
}
|
||
|
}).join('\n');
|
||
|
|
||
|
return tabulated;
|
||
|
}
|
||
|
|
||
|
function serializeSymbol(s) {
|
||
|
if (s instanceof RegExp) {
|
||
|
return s.toString();
|
||
|
} else if (s.token) {
|
||
|
return s.token;
|
||
|
} else {
|
||
|
return JSON.stringify(s);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function serializeRule(rule, builtinPostprocessors) {
|
||
|
var ret = '{';
|
||
|
ret += '"name": ' + JSON.stringify(rule.name);
|
||
|
ret += ', "symbols": [' + rule.symbols.map(serializeSymbol).join(', ') + ']';
|
||
|
if (rule.postprocess) {
|
||
|
if(rule.postprocess.builtin) {
|
||
|
rule.postprocess = builtinPostprocessors[rule.postprocess.builtin];
|
||
|
}
|
||
|
ret += ', "postprocess": ' + tabulateString(dedentFunc(rule.postprocess), ' ', {indentFirst: false});
|
||
|
}
|
||
|
ret += '}';
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
var generate = function (parser, exportName) {
|
||
|
if(!parser.config.preprocessor) {
|
||
|
parser.config.preprocessor = "_default";
|
||
|
}
|
||
|
|
||
|
if(!generate[parser.config.preprocessor]) {
|
||
|
throw new Error("No such preprocessor: " + parser.config.preprocessor)
|
||
|
}
|
||
|
|
||
|
return generate[parser.config.preprocessor](parser, exportName);
|
||
|
};
|
||
|
|
||
|
generate.js = generate._default = generate.javascript = function (parser, exportName) {
|
||
|
var output = "// Generated automatically by nearley, version " + parser.version + "\n";
|
||
|
output += "// http://github.com/Hardmath123/nearley\n";
|
||
|
output += "(function () {\n";
|
||
|
output += "function id(x) { return x[0]; }\n";
|
||
|
output += parser.body.join('\n');
|
||
|
output += "var grammar = {\n";
|
||
|
output += " Lexer: " + parser.config.lexer + ",\n";
|
||
|
output += " ParserRules: " +
|
||
|
serializeRules(parser.rules, generate.javascript.builtinPostprocessors)
|
||
|
+ "\n";
|
||
|
output += " , ParserStart: " + JSON.stringify(parser.start) + "\n";
|
||
|
output += "}\n";
|
||
|
output += "if (typeof module !== 'undefined'"
|
||
|
+ "&& typeof module.exports !== 'undefined') {\n";
|
||
|
output += " module.exports = grammar;\n";
|
||
|
output += "} else {\n";
|
||
|
output += " window." + exportName + " = grammar;\n";
|
||
|
output += "}\n";
|
||
|
output += "})();\n";
|
||
|
return output;
|
||
|
};
|
||
|
|
||
|
generate.javascript.builtinPostprocessors = {
|
||
|
"joiner": "function joiner(d) {return d.join('');}",
|
||
|
"arrconcat": "function arrconcat(d) {return [d[0]].concat(d[1]);}",
|
||
|
"arrpush": "function arrpush(d) {return d[0].concat([d[1]]);}",
|
||
|
"nuller": "function(d) {return null;}",
|
||
|
"id": "id"
|
||
|
}
|
||
|
|
||
|
generate.module = generate.esmodule = function (parser, exportName) {
|
||
|
var output = "// Generated automatically by nearley, version " + parser.version + "\n";
|
||
|
output += "// http://github.com/Hardmath123/nearley\n";
|
||
|
output += "function id(x) { return x[0]; }\n";
|
||
|
output += parser.body.join('\n');
|
||
|
output += "let Lexer = " + parser.config.lexer + ";\n";
|
||
|
output += "let ParserRules = " + serializeRules(parser.rules, generate.javascript.builtinPostprocessors) + ";\n";
|
||
|
output += "let ParserStart = " + JSON.stringify(parser.start) + ";\n";
|
||
|
output += "export default { Lexer, ParserRules, ParserStart };\n";
|
||
|
return output;
|
||
|
};
|
||
|
|
||
|
generate.cs = generate.coffee = generate.coffeescript = function (parser, exportName) {
|
||
|
var output = "# Generated automatically by nearley, version " + parser.version + "\n";
|
||
|
output += "# http://github.com/Hardmath123/nearley\n";
|
||
|
output += "do ->\n";
|
||
|
output += " id = (d) -> d[0]\n";
|
||
|
output += tabulateString(dedentFunc(parser.body.join('\n')), ' ') + '\n';
|
||
|
output += " grammar = {\n";
|
||
|
output += " Lexer: " + parser.config.lexer + ",\n";
|
||
|
output += " ParserRules: " +
|
||
|
tabulateString(
|
||
|
serializeRules(parser.rules, generate.coffeescript.builtinPostprocessors),
|
||
|
' ',
|
||
|
{indentFirst: false})
|
||
|
+ ",\n";
|
||
|
output += " ParserStart: " + JSON.stringify(parser.start) + "\n";
|
||
|
output += " }\n";
|
||
|
output += " if typeof module != 'undefined' "
|
||
|
+ "&& typeof module.exports != 'undefined'\n";
|
||
|
output += " module.exports = grammar;\n";
|
||
|
output += " else\n";
|
||
|
output += " window." + exportName + " = grammar;\n";
|
||
|
return output;
|
||
|
};
|
||
|
|
||
|
generate.coffeescript.builtinPostprocessors = {
|
||
|
"joiner": "(d) -> d.join('')",
|
||
|
"arrconcat": "(d) -> [d[0]].concat(d[1])",
|
||
|
"arrpush": "(d) -> d[0].concat([d[1]])",
|
||
|
"nuller": "() -> null",
|
||
|
"id": "id"
|
||
|
};
|
||
|
|
||
|
generate.ts = generate.typescript = function (parser, exportName) {
|
||
|
var output = "// Generated automatically by nearley, version " + parser.version + "\n";
|
||
|
output += "// http://github.com/Hardmath123/nearley\n";
|
||
|
output += "// Bypasses TS6133. Allow declared but unused functions.\n";
|
||
|
output += "// @ts-ignore\n";
|
||
|
output += "function id(d: any[]): any { return d[0]; }\n";
|
||
|
output += parser.customTokens.map(function (token) { return "declare var " + token + ": any;\n" }).join("")
|
||
|
output += parser.body.join('\n');
|
||
|
output += "\n";
|
||
|
output += "interface NearleyToken {\n";
|
||
|
output += " value: any;\n";
|
||
|
output += " [key: string]: any;\n";
|
||
|
output += "};\n";
|
||
|
output += "\n";
|
||
|
output += "interface NearleyLexer {\n";
|
||
|
output += " reset: (chunk: string, info: any) => void;\n";
|
||
|
output += " next: () => NearleyToken | undefined;\n";
|
||
|
output += " save: () => any;\n";
|
||
|
output += " formatError: (token: never) => string;\n";
|
||
|
output += " has: (tokenType: string) => boolean;\n";
|
||
|
output += "};\n";
|
||
|
output += "\n";
|
||
|
output += "interface NearleyRule {\n";
|
||
|
output += " name: string;\n";
|
||
|
output += " symbols: NearleySymbol[];\n";
|
||
|
output += " postprocess?: (d: any[], loc?: number, reject?: {}) => any;\n";
|
||
|
output += "};\n";
|
||
|
output += "\n";
|
||
|
output += "type NearleySymbol = string | { literal: any } | { test: (token: any) => boolean };\n";
|
||
|
output += "\n";
|
||
|
output += "interface Grammar {\n";
|
||
|
output += " Lexer: NearleyLexer | undefined;\n";
|
||
|
output += " ParserRules: NearleyRule[];\n";
|
||
|
output += " ParserStart: string;\n";
|
||
|
output += "};\n";
|
||
|
output += "\n";
|
||
|
output += "const grammar: Grammar = {\n";
|
||
|
output += " Lexer: " + parser.config.lexer + ",\n";
|
||
|
output += " ParserRules: " + serializeRules(parser.rules, generate.typescript.builtinPostprocessors, " ") + ",\n";
|
||
|
output += " ParserStart: " + JSON.stringify(parser.start) + ",\n";
|
||
|
output += "};\n";
|
||
|
output += "\n";
|
||
|
output += "export default grammar;\n";
|
||
|
|
||
|
return output;
|
||
|
};
|
||
|
|
||
|
generate.typescript.builtinPostprocessors = {
|
||
|
"joiner": "(d) => d.join('')",
|
||
|
"arrconcat": "(d) => [d[0]].concat(d[1])",
|
||
|
"arrpush": "(d) => d[0].concat([d[1]])",
|
||
|
"nuller": "() => null",
|
||
|
"id": "id"
|
||
|
};
|
||
|
|
||
|
return generate;
|
||
|
|
||
|
}));
|