Offering Access to Parser
cy via Digitalmars-d
digitalmars-d at puremagic.com
Tue Feb 9 14:14:25 PST 2016
I know macros are an unpopular subject in D, but I think there's
a way to get mostly equivalent capabilities to macros, without
changing the language at all, simply by standardizing access to
the compiler's own D language parser.
There are already 10 separate parsers for D here:
http://wiki.dlang.org/Lexers_Parsers
All these parsers are pretty much written from scratch (one even
forked from dmd itself) and they all do pretty much the same
thing: take a string of code, and turn it into an AST. Turning
that AST back into valid D code is itself a rather difficult and
error prone process, but if you could, then you could simply do
something like:
import some.parser;
string foo(string bar) =
unparse(IfDeclaration(parse(bar),parse(q{writeln("yay")}),parse(q{writeln("boo")}));
void main() {
mixin foo!"true";
mixin foo!"false";
}
D isn't a particularly hard to parse language, so it's not too
hard to implement these parsers, but they're definitely
reinventing the wheel, and there's no assurance that future
language features won't break them. But within each D compiler
(I'm pretty sure?) there is already a parser, that produces (and
manipulates) an AST. For DMD, the parser is written in D itself!
Using it would (in theory) be as simple as copying all the ddmd
modules into your source directory and importing ddmd.parse.
Eliminating the need to maintain all those third party parsers is
as simple as having the compiler itself provide the parser as a
module.
There is additionally a huge advantage to code being able to use
the compiler's D parser, that third party parsers cannot match.
The D compiler actually uses the AST generated by its parser.
With the other parsers, you have to somehow figure out how to
"unparse" their AST into an opaque string of D code, before you
can supply that new code as a mixin, but if you used the
compiler's own parser, it could accept an AST as a mixin omitting
the "parse" step it normally does on mixins.
So the above would end up more like:
import std.parser;
AST foo(string bar) = IfDeclaration(parse(bar),
parse(q{writeln("yay")}), parse(q{writeln("boo")}));
void main() {
mixin foo!"true";
mixin foo!"false";
}
omitting the complicated and error prone "unparse()" step
entirely, not to mention removing the degradation in compilation
speed if you have to unparse, and then re-parse an AST.
I'm not sure if it would be possible to have the parser available
at runtime, but it seems like you could compile it into the
program just like any other module.
More information about the Digitalmars-d
mailing list