Hi, I try to figure out, whether a port of boost::spirit to D would be possible.
This library is heavily using C++ operator overloading.
Now there are some problems I figured out:
C++ allows the * operator to be overloaded in case of dereferencing.
Spirit uses it as the "kleene star": *(expr) means repeat expr 0 or more times.
D has opMul(_r), which overloads: "a*b" and "null*b", but not: "*b" since the latter means dereferencing.
In the docs it's said "!", "&&" and "||" will likely never be overloadable.
C++ allows all of them to be overloaded and spirit makes use of it.
"!(expr)" means expr is optional (so 0 or 1 match). "||" and "&&" are used for sequential matching.
So my feature req for D:
without further arguments:
*(expr) -> opDeref()
!(expr) -> opNot()
&(expr) -> opAddr()
WITH one more argument and _r:
expr1 && expr2 -> opAndAnd
expr1 || expr2 -> opOrOr
expr1 , expr2 -> opComma
The following is not possible in C++:
value = expr1 expr2;
Because nothing is not overloadable as an operator.
What about opNothing in D ;) ?
Thanks in advance,
Daniel
Comment #1 by wbaxter — 2007-06-03T19:18:31Z
As Jarrett pointed out in the NG follow-up, porting Spirit line-by-line is undoutedly the wrong way to go about it.
With spirit you can have the syntax:
boost::spirit::rule<ScannerT> factor, term;
term = factor >> *( ( '*' >> factor) | ( '/' >> factor ) );
Which admittedly looks pretty similar to BNF.
But with the compile time text processing stuff that's been going into D you can just use the BNF:
mixin(Rule!(
"term ::= factor ( ( '*' factor ) | ( '/' factor ) )*"
));
And maybe eventually the 'mixin' part won't be necessary either, but for now it is.
Operator overloading abuse is cute, but it's just working around the lack of ability in C++ to do more generic compile-time processing. The biggest issue with operator overloading for this kind of thing is that you're stuck with the built-in precedence rules and operators (*prefix* kleen star?)
One approach might be to build a standard API-based syntax for a parser-generator first (like C# ports of boost - http://www.codeproject.com/csharp/spart.asp). Then use the compile time string facilities in D to translate BNF strings to that API.
Just a thought.
But in any event, I can tell you for sure that "I want to use unary * as a Kleen star operator so D needs to have opDeref()" is not an argument that will gain any traction with Walter. He's a firm believer in operator overloads not changing the semantics of the underlying operator.
Comment #2 by Daniel919 — 2007-06-04T03:43:00Z
It would be really nice without the need of writing "mixin" and with more compile-time function capabilities.
Having an API and then translate the EBNF string onto it sounds like a good idea.
This way the EBNF can be kept 100%, so there would be no reason for having ">>" like it's necessary in spirit.
Thanks for clarifying this.