Hacker News new | past | comments | ask | show | jobs | submit login
How to parse text for a DSL at compile time? (C++) (stackoverflow.com)
44 points by Cieplak on Aug 21, 2017 | hide | past | favorite | 20 comments



It seems like doing this in C++ is overly complex. In language's like Nim where you can just executed ordinary code at compile-time it would be far simpler.


The author suggests he wants to "expand this little DSL later so does something a little more complicated using some non-C++ syntax", so Nim's ordinary code evaluation at compile time wouldn't help either. On the other hand, if he restricted himself to just using C++ expressions, he would be fine using constexpr (assuming he can use newer standards of the language).


That's what the OP meant with "Yes. That's right." In C++ circles, this loosely translates to "Let's use this ridiculously unwieldy if not downright stupid mechanism to do something just because we can".


I know it is fashionable to bash on C++ lately but I dont fully understand the motivation behind it. Could you please elaborate what drove you to write a post expressing your derision about C++? Does the frustration come from trying to use the language in the past and running into its limitations?


I don't know about the original comment writer. But my frustration comes because of overly complex, while there would be simpler way to do that.


what would be the simpler way to translate any string in a given DSL in an expression at compile time in C++ ?


'const char* transformSrc_MyExpr(const char* src);'

We're the compiler to invoke some function like that at compile time, it would be much more simple.

I'm not suggesting this exactally, or even something very similar, but serves as an example.


Hey dom96, while your intentions are probably fine, it would help to copy the first two lines of your HN bio here.

eg. Disclaimer "I am one of the primary developers of the Nim programming language, as well as many tools and libraries for Nim. I am also currently writing a book about Nim called Nim in Action."

That carries both more weight to your answer as you clearly know Nim very well as well as gives people the correct perspective.


Good point. I will do that next time :)


Does it extend to C or to Nim itself? Rust macros extend to Rust, and as an input it can receive any valid tokens (the only condition being to have all opening and closing () {} [] match correctly).

Rust procedural macros are one of the reasons I started using Rust.


It extends to Nim, and macros can also receive any valid Nim token. Alternatively you can also pass a string literal and parse it in your macro.

Nim's metaprogramming support is quite extensive, possibly even more so than Rust's. If this is something that interests you then you should check it out.

As an example of what's possible: async await in Nim is implemented entirely via a macro[1], the `=>` operator for closures is also implemented as a macro[2].

1 - Example chat app client using async await: https://github.com/dom96/nim-in-action-code/blob/master/Chap...

2 - Implementation of `=>`: https://github.com/nim-lang/Nim/blob/devel/lib/pure/future.n...


That's good to know, thanks. In many ways Nim resembles my ideal language that I wanted to make time ago. Rust is still above on my list, though. May give Nim a try if I get too frustrated with Rust.


Each new iterations of C++ introduces more "constexpr" elements. It's a C++ sub language to execute things "possibly at compile time". The language as a whole is too complex (ex: threads, futures, i/o) to fully execute at compile time without introducing its own set of insanities. Along with the future compile time introspection support it will improve.

For now, abusing of the template system is still popular.


I've always wondered why this isn't a first class language feature. You could make something like JOOQ or LINQ that just hooks the compiler itself at build time to extend the language arbitrarily. And no worries about outdated versions, you hooks could also polyfill newer syntax and features if you can hook at parse time.

This would result in a whole new breed of abominations but perhaps something decent would come of it


It is, in lots of languages. It is usually called "compile time macros" or "macros".

In lots of languages the macros run in the language itself, for example in Lisp, Scala or Nim.

In C++, compile time macros are run in two separate languages: 1 the "pre-processor" and 2 "C++ templates"


> you can just executed ordinary code at compile-time

Another 'recent' language that addresses this to the point of being its significant existential justification is D


In practice, what you would do is write a preprocessing/code-generating tool that runs in the build environment, as part of the toolchain.


+1.

In Visual Studio, a good built-in mechanism for that is T4 text templates.


D has this use case solved in a really nice way. All you have to do is write a function that converts the DSL into D code and then do something like `mixin(my_dsl_converter('foobar'))`.


This may not be quite what the original poster is looking for, but boost::spirit allows one to build DSLs directly in the code. The DSL is then used to parse constructs and execute the results.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: