Simple example using Y combinator?
rapodaca opened this issue · 4 comments
I'd like to implement a grammar that I think requires recursion.
The input "a(b(c)d)e" should produce:
[
[
"a"
],
[
"(",
[
[
"b"
],
[
"(",
[
[
"c"
]
],
")"
],
[
"d"
]
],
")"
],
[
"e"
]
]
My grammar so far is:
const grammar = function (token, all, any, plus, optional, node) {
let open = token(/(\()/g, 'open');
let close = token(/(\))/g, 'close');
let letter = token(/([a-z])/g, 'letter');
let run = Y(function (thisRun) {
return node(any(plus(letter), all(open, thisRun, close)), reduceRun);
});
let line = node(plus(run), reduceLine)
return line;
};
const Y = function (gen) {
return (function(f) {return f(f)})( function(f) {
return gen(function() {return f(f).apply(null, arguments)});
});
};
const reduceRun = (run) => {
return run.map((u) => {
return u;
});
};
const reduceLine = (line) => {
return line;
};
module.exports = grammar;
I use the grammar like this:
const Parser = require('rd-parse');
const grammar = require('./grammar');
let input = 'a(b(c)d)e';
let p = new Parser(grammar);
let ast = p.parse(input);
console.log(JSON.stringify(ast, null, 2));
Instead of the output I'm after, this code fails with the error: "Error: Parsing failed"
How can I fix this problem? Alternatively, are there any examples illustrating how (and why) to use the Y combinator?
The documentation refers to the examples, but I'm not able to see why my code fails from them.
I noticed this modified grammar does the job:
const grammar = function (token, all, any, plus, optional, node) {
let open = token(/(\()/g, 'open');
let close = token(/(\))/g, 'close');
let letter = token(/([a-z])/g, 'letter');
return Y(function (thisGrammar) {
let run = node(any(plus(letter), all(open, thisGrammar, close)), reduceRun);
let line = node(plus(run), reduceLine);
return line;
});
};
const Y = function (gen) {
return (function(f) {return f(f)})( function(f) {
return gen(function() {return f(f).apply(null, arguments)});
});
};
const reduceRun = (run) => {
return run.map((u) => {
return u;
});
};
const reduceLine = (line) => {
return line;
};
module.exports = grammar;
However, it appears to require recursion over the entire grammar. Is it possible to define recursion over a more limited set of grammar rules as I originally tried?
Thanks for taking a look. You're right, and I have a much better handle on how to use rd-parse now. The y combinator part also makes sense, and I ended up going with something similar to my second example.
Glad to hear that it works for you!