How to parse text for a DSL at compile time? (C++)

(stackoverflow.com)

44 points | by Cieplak 2412 days ago

5 comments

  • dom96 2411 days ago
    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.
    • akrasuski1 2411 days ago
      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).
    • ndh2 2411 days ago
      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".
      • dman 2411 days ago
        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?
        • 0xFFC 2411 days ago
          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.
          • jcelerier 2411 days ago
            what would be the simpler way to translate any string in a given DSL in an expression at compile time in C++ ?
            • Arelius 2411 days ago
              '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.

    • wila 2411 days ago
      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.

      • dom96 2411 days ago
        Good point. I will do that next time :)
    • DiThi 2411 days ago
      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.

      • dom96 2411 days ago
        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...

        • DiThi 2410 days ago
          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.
    • Elv13 2411 days ago
      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.

    • slackingoff2017 2411 days ago
      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

      • rtb 2411 days ago
        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"

    • srean 2410 days ago
      > 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

  • kazinator 2410 days ago
    In practice, what you would do is write a preprocessing/code-generating tool that runs in the build environment, as part of the toolchain.
    • Const-me 2410 days ago
      +1.

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

  • Doxin 2409 days ago
    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'))`.
  • stargrazer 2410 days ago
    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.