2019-08-31 20:51:14 -07:00

60 lines
1.7 KiB
JavaScript

const nearley = require('nearley');
const compile = require('nearley/lib/compile');
const generate = require('nearley/lib/generate');
const nearleyGrammar = require('nearley/lib/nearley-language-bootstrapped');
const Filter = require('broccoli-filter');
/**
* Will transform .ne files into .js files with Grammar Compiled Rules
* that are ready to consume by nearly parser.
*
* We are using Filter as a base Broccoli plugin
*/
class BroccoliNearley extends Filter {
/**
* Extending constructor to add '.ne' extensions
* @param {*} inputNode
*/
constructor(inputNode) {
super(inputNode);
this.extensions = ['ne'];
this.targetExtension = 'js';
}
/**
* Process a file: Will compile it and prepare it to be consumed.
* @param {*} content File content with grammar
* @param {*} relativePath path of the original file
*/
processString(content, relativePath) {
const code = this.compileGrammar(content);
return `define('${relativePath.replace(/\.ne/, '')}', ['exports'], function(exports) {
const module = { exports: {} };
${code}
exports.default = module.exports;
});`;
}
/**
* Compile Grammar as specified in Nearley Docs.
* @param {*} sourceCode content of ne file
*/
compileGrammar(sourceCode) {
// Parse the grammar source into an AST
const grammarParser = new nearley.Parser(nearleyGrammar);
grammarParser.feed(sourceCode);
const grammarAst = grammarParser.results[0]; // TODO check for errors
// Compile the AST into a set of rules
const grammarInfoObject = compile(grammarAst, {});
// Generate JavaScript code from the rules
const grammarJs = generate(grammarInfoObject, 'grammar');
return grammarJs;
}
}
module.exports = BroccoliNearley;