Skip to content

Commit 18e0750

Browse files
committedFeb 20, 2017
JavaScript module generation SimplePEG#1
1 parent 50619d1 commit 18e0750

File tree

5 files changed

+81
-19
lines changed

5 files changed

+81
-19
lines changed
 

‎src/speg.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var SPEG_actions_visitor = require('./speg_visitor').SPEG_actions_visitor;
2+
var SPEG_module_visitor = require('./speg_module_visitor').SPEG_module_visitor;
23
var SPEG_parser = require('./speg_parser');
34
var rd = require('./rd_parser');
45
var ex = require('./exceptions');
@@ -56,6 +57,19 @@ SPEG.prototype.parse = function(grammar, text) {
5657
}
5758
};
5859

60+
SPEG.prototype.parse_module = function(grammar) {
61+
this.module_visitor = new SPEG_module_visitor();
62+
var speg_ast = this.parser.parse(grammar);
63+
if (speg_ast) {
64+
return this.module_visitor.visit(speg_ast);
65+
} else {
66+
throw new ex.GrammarParseError('Failed to parse grammar: \n\n' + this.parser.get_last_error());
67+
}
68+
}
69+
5970
module.exports = {
60-
SPEG: SPEG
71+
SPEG: SPEG,
72+
rd: rd,
73+
TextParseError: ex.TextParseError,
74+
GrammarParseError: ex.GrammarParseError
6175
};

‎src/speg_module_visitor.js

+37-18
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
var rd = require('./rd_parser');
22

3-
function SPEG_actions_visitor() {
3+
function SPEG_module_visitor() {
44
this.actions = new SPEG_actions();
55
}
6-
SPEG_actions_visitor.prototype.visit = function(node) {
6+
SPEG_module_visitor.prototype.visit = function(node) {
7+
this.firstRule = null;
78
if (node.children) {
89
node.children = node.children.map(function(child){
910
return this.visit(child);
@@ -22,26 +23,47 @@ SPEG_actions.prototype.noop = function(node) {
2223
};
2324

2425
SPEG_actions.prototype.peg = function(node) {
25-
return node.children[3];
26+
var module_source =
27+
'var simplepeg = require(\'simplepeg\');\n' +
28+
'var rd = simplepeg.rd;\n' +
29+
'function SPEG() {\n' +
30+
' this.state = null;\n' +
31+
'}\n' +
32+
'SPEG.prototype.parse_text = function(text) {\n' +
33+
' this.state = { text: text, position: 0 };\n' +
34+
' var ast = ' + this.firstRule + '()(this.state);\n' +
35+
' if (ast) {\n' +
36+
' return ast;\n' +
37+
' } else {\n' +
38+
' throw new simplepeg.TextParseError(\'Failed to parse text: \\n\\n\' + rd.get_last_error(this.state))\n' +
39+
' }\n' +
40+
'};\n' +
41+
'module.exports = {\n' +
42+
' SPEG: SPEG\n' +
43+
'};\n\n' + node.children[3].join('\n');
44+
45+
return module_source;
2646
};
2747

2848
SPEG_actions.prototype.parsing_body = function(node) {
2949
node.children = node.children.map(function(child){
3050
return child.children[0];
3151
});
32-
return node;
52+
return node.children;
3353
};
3454

3555
SPEG_actions.prototype.parsing_rule = function(node) {
3656
var rule = node.children[4];
3757
var ruleName = node.children[0].match;
38-
return '{\n' +
39-
'name: ' + ruleName + ',\n' +
40-
'parser: function(state) {\n' +
58+
if (!this.firstRule) {
59+
this.firstRule = ruleName;
60+
}
61+
return 'function ' + ruleName + '() {\n' +
62+
'return function(state) {\n' +
4163
'var start = state.position;\n' +
42-
'var ast = ' + rule + '(state);\n' +
64+
'var ast = (' + rule + ')(state);\n' +
4365
'if (ast) {\n' +
44-
'ast.rule = ' + ruleName + ';\n' +
66+
'ast.rule = "' + ruleName + '";\n' +
4567
'if (!state.succesfullRules) {\n' +
4668
'state.succesfullRules = [];\n' +
4769
'}\n' +
@@ -56,13 +78,13 @@ SPEG_actions.prototype.parsing_rule = function(node) {
5678
'state.failedRules = [];\n' +
5779
'}\n' +
5880
'state.failedRules.push({\n' +
59-
'rule: ' + ruleName + ',\n' +
81+
'rule: "' + ruleName + '",\n' +
6082
'start_position: start\n' +
6183
'});\n' +
6284
'}\n' +
6385
'return ast;\n' +
6486
'}\n' +
65-
'}'
87+
'}';
6688
};
6789

6890
SPEG_actions.prototype.parsing_expression = function(node) {
@@ -140,24 +162,21 @@ SPEG_actions.prototype.parsing_optional = function(node) {
140162
};
141163

142164
SPEG_actions.prototype.parsing_string = function(node) {
143-
return 'rd.string(' + node.children[1].match + ')';
144-
//.replace(/\\\\/g, '\\')
145-
//.replace(/\\"/g, '"')
146-
//);
165+
return 'rd.string("' + node.children[1].match + '")';
147166
};
148167

149168
SPEG_actions.prototype.parsing_regex_char = function(node) {
150-
return 'rd.regex_char(' + node.children[0].match + ')';
169+
return 'rd.regex_char(/' + node.children[0].match + '/)';
151170
};
152171

153172
SPEG_actions.prototype.parsing_rule_call = function(node) {
154-
return 'rd.call_rule_by_name(' + node.match + ')';
173+
return 'rd.rec(' + node.match + ')';
155174
};
156175

157176
SPEG_actions.prototype.parsing_end_of_file = function() {
158177
return 'rd.end_of_file()';
159178
};
160179

161180
module.exports = {
162-
SPEG_actions_visitor: SPEG_actions_visitor
181+
SPEG_module_visitor: SPEG_module_visitor
163182
};
File renamed without changes.
File renamed without changes.

‎test/speg_module.fixtures.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var SPEG = require('./../src/speg').SPEG;
2+
var fs = require('fs');
3+
var path = require('path');
4+
var recursiveReadSync = require('recursive-readdir-sync');
5+
var valid_files = recursiveReadSync('./test/speg_fixtures');
6+
7+
describe('speg module - fixtures - ', function() {
8+
valid_files = valid_files.filter(function(filename) {
9+
return /\.peg$/.test(filename);
10+
})
11+
for (var i = 0, len = valid_files.length; i < len; i++) {
12+
it('should parse - ' + valid_files[i], (function (filename) {
13+
return function () {
14+
var name = path.basename(filename);
15+
var grammar = fs.readFileSync(filename, "utf8");
16+
var text = fs.readFileSync(path.join('./test/speg_fixtures/', name + '.txt'), "utf8");
17+
var result = fs.readFileSync(path.join('./test/speg_fixtures/', name + '.json'), "utf8");
18+
var speg = new SPEG();
19+
var module_source = speg.parse_module(grammar);
20+
fs.writeFileSync('./parser.js', module_source);
21+
delete require.cache[path.resolve('./parser.js')];
22+
var parser = new (require('./../parser').SPEG);
23+
fs.unlinkSync('./parser.js');
24+
var ast = parser.parse_text(text);
25+
ast.should.deep.equal(JSON.parse(result));
26+
}
27+
}(valid_files[i])));
28+
}
29+
});

0 commit comments

Comments
 (0)
Please sign in to comment.