jison-es
Version:
Fork of jison that emits parsers as ES modules
382 lines (317 loc) • 9.9 kB
JavaScript
var Jison = require("../setup").Jison,
Lexer = require("../setup").Lexer,
assert = require("assert");
var fs = require('fs');
var path = require('path');
exports["test amd module generator"] = function() {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
tokens: "x y",
startSymbol: "A",
bnf: {
"A" :[ 'A x',
'A y',
'' ]
}
};
var input = "xyxxxy";
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateAMDModule();
var parser = null,
define = function(callback){
// temporary AMD-style define function, for testing.
parser = callback();
};
eval(parserSource);
assert.ok(parser.parse(input));
};
exports["test commonjs module generator"] = function () {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
tokens: "x y",
startSymbol: "A",
bnf: {
"A" :[ 'A x',
'A y',
'' ]
}
};
var input = "xyxxxy";
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateCommonJSModule();
var exports = {};
eval(parserSource);
assert.ok(exports.parse(input));
};
exports["test module generator"] = function () {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
tokens: "x y",
startSymbol: "A",
bnf: {
"A" :[ 'A x',
'A y',
'' ]
}
};
var input = "xyxxxy";
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateModule();
eval(parserSource);
assert.ok(parser.parse(input));
};
exports["test module generator with module name"] = function () {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
tokens: "x y",
startSymbol: "A",
bnf: {
"A" :[ 'A x',
'A y',
'' ]
}
};
var input = "xyxxxy";
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generate({moduleType: "js", moduleName: "parsey"});
eval(parserSource);
assert.ok(parsey.parse(input));
};
exports["test module generator with namespaced module name"] = function () {
var lexData = {
rules: [
["x", "return 'x';"],
["y", "return 'y';"]
]
};
var grammar = {
tokens: "x y",
startSymbol: "A",
bnf: {
"A" :[ 'A x',
'A y',
'' ]
}
};
var compiler = {};
var input = "xyxxxy";
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateModule({moduleName: "compiler.parser"});
eval(parserSource);
assert.ok(compiler.parser.parse(input));
};
exports["test module include"] = function () {
var grammar = {
"comment": "ECMA-262 5th Edition, 15.12.1 The JSON Grammar. (Incomplete implementation)",
"author": "Zach Carter",
"lex": {
"macros": {
"digit": "[0-9]",
"exp": "([eE][-+]?{digit}+)"
},
"rules": [
["\\s+", "/* skip whitespace */"],
["-?{digit}+(\\.{digit}+)?{exp}?", "return 'NUMBER';"],
["\"[^\"]*", function(){
if(yytext.charAt(yyleng-1) == '\\') {
// remove escape
yytext = yytext.substr(0,yyleng-2);
this.more();
} else {
yytext = yytext.substr(1); // swallow start quote
this.input(); // swallow end quote
return "STRING";
}
}],
["\\{", "return '{'"],
["\\}", "return '}'"],
["\\[", "return '['"],
["\\]", "return ']'"],
[",", "return ','"],
[":", "return ':'"],
["true\\b", "return 'TRUE'"],
["false\\b", "return 'FALSE'"],
["null\\b", "return 'NULL'"]
]
},
"tokens": "STRING NUMBER { } [ ] , : TRUE FALSE NULL",
"start": "JSONText",
"bnf": {
"JSONString": [ "STRING" ],
"JSONNumber": [ "NUMBER" ],
"JSONBooleanLiteral": [ "TRUE", "FALSE" ],
"JSONText": [ "JSONValue" ],
"JSONValue": [ "JSONNullLiteral",
"JSONBooleanLiteral",
"JSONString",
"JSONNumber",
"JSONObject",
"JSONArray" ],
"JSONObject": [ "{ }",
"{ JSONMemberList }" ],
"JSONMember": [ "JSONString : JSONValue" ],
"JSONMemberList": [ "JSONMember",
"JSONMemberList , JSONMember" ],
"JSONArray": [ "[ ]",
"[ JSONElementList ]" ],
"JSONElementList": [ "JSONValue",
"JSONElementList , JSONValue" ]
}
};
var gen = new Jison.Generator(grammar);
var parserSource = gen.generateModule();
eval(parserSource);
assert.ok(parser.parse(JSON.stringify(grammar.bnf)));
};
exports["test module include code"] = function () {
var lexData = {
rules: [
["y", "return 'y';"]
]
};
var grammar = {
bnf: {
"E" :[ ["E y", "return test();"],
"" ]
},
moduleInclude: "function test(val) { return 1; }"
};
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateCommonJSModule();
var exports = {};
eval(parserSource);
assert.equal(parser.parse('y'), 1, "semantic action");
};
exports["test lexer module include code"] = function () {
var lexData = {
rules: [
["y", "return test();"]
],
moduleInclude: "function test() { return 1; }"
};
var grammar = {
bnf: {
"E" :[ ["E y", "return $2;"],
"" ]
}
};
var gen = new Jison.Generator(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateCommonJSModule();
var exports = {};
eval(parserSource);
assert.equal(parser.parse('y'), 1, "semantic action");
};
exports["test generated parser instance creation"] = function () {
var grammar = {
lex: {
rules: [
["y", "return 'y'"]
]
},
bnf: {
"E" :[ ["E y", "return $2;"],
"" ]
}
};
var gen = new Jison.Generator(grammar);
var parserSource = gen.generateModule();
eval(parserSource);
var p = new parser.Parser;
assert.equal(p.parse('y'), 'y', "semantic action");
parser.blah = true;
assert.notEqual(parser.blah, p.blah, "shouldn't inherit props");
};
exports["test module include code using generator from parser"] = function () {
var lexData = {
rules: [
["y", "return 'y';"]
]
};
var grammar = {
bnf: {
"E" :[ ["E y", "return test();"],
"" ]
},
moduleInclude: "function test(val) { return 1; }"
};
var gen = new Jison.Parser(grammar);
gen.lexer = new Lexer(lexData);
var parserSource = gen.generateCommonJSModule();
var exports = {};
eval(parserSource);
assert.equal(parser.parse('y'), 1, "semantic action");
};
exports["test module include with each generator type"] = function () {
var lexData = {
rules: [
["y", "return 'y';"]
]
};
var grammar = {
bnf: {
"E" :[ ["E y", "return test();"],
"" ]
},
moduleInclude: "var TEST_VAR;"
};
var gen = new Jison.Parser(grammar);
gen.lexer = new Lexer(lexData);
['generateModule', 'generateAMDModule', 'generateCommonJSModule']
.map(function(type) {
var source = gen[type]();
assert.ok(/TEST_VAR/.test(source), type + " supports module include");
});
};
// test for issue #246
exports["test compiling a parser/lexer"] = function () {
var grammar =
'// Simple "happy happy joy joy" parser, written by Nolan Lawson\n' +
'// Based on the song of the same name.\n\n' +
'%lex\n%%\n\n\\s+ /* skip whitespace */\n' +
'("happy") return \'happy\'\n' +
'("joy") return \'joy\'\n' +
'<<EOF>> return \'EOF\'\n\n' +
'/lex\n\n%start expressions\n\n' +
'%ebnf\n\n%%\n\n' +
'expressions\n : e EOF\n {return $1;}\n ;\n\n' +
'e\n : phrase+ \'joy\'? -> $1 + \' \' + yytext \n ;\n\n' +
'phrase\n : \'happy\' \'happy\' \'joy\' \'joy\' ' +
' -> [$1, $2, $3, $4].join(\' \'); \n ;';
var parser = new Jison.Parser(grammar);
var generated = parser.generate();
var tmpFile = path.resolve(__dirname, 'tmp-parser.js');
fs.writeFileSync(tmpFile, generated);
var parser2 = require('./tmp-parser');
assert.ok(parser.parse('happy happy joy joy joy') === 'happy happy joy joy joy',
'original parser works');
assert.ok(parser2.parse('happy happy joy joy joy') === 'happy happy joy joy joy',
'generated parser works');
fs.unlinkSync(tmpFile);
};