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