yhirose / cpp-peglib

A single file C++ header-only PEG (Parsing Expression Grammars) library
MIT License
900 stars 112 forks source link

Using cpp-peglib inside Circle #65

Closed seanbaxter closed 3 years ago

seanbaxter commented 5 years ago

Hi, great work on the library. I've been writing my own C++ compiler, and I've found a very novel use for cpp-peglib. A friend of mine has been using cpp-peglib with Circle to generate code targeting an exotic architecture. I decided to port calc3.cc as a tutorial for using cpp-peglib at compile time to define and implement DSLs in C++.

https://github.com/seanbaxter/circle/blob/master/peg_dsl/peg_dsl.md

Basically what I do is #include peglib.h and make a compile-time instance of peg::parser. Circle has an integrated interpreter so any code can be executed during source translation. I beefed up the calc3 grammar by adding an IDENTIFIER rule. Then I create C++ functions that expand a Circle macro and feed it the text to be parsed in a string literal. A Circle macro invokes the parser object (at compile time!), gets back the AST, and traverses the AST using some other macros. IDENTIFIER nodes in the AST are evaluated with @expressions, which lexes, parses and injects the contained text. That is, the result object for an IDENTIFIER node is an lvalue to the object named. The other parts of the AST are processed similarly.

When all this is done, compilation ends, and you're left with a C++ program that has the code you specified in the string lowered to LLVM IR. There is no remnant of the parser in the executable, because its job was to translate the DSL into an AST at compile time.

Since uses of parsing libraries is to make developer tools anyway, having a C++ compiler serve as a host language or a scripting language to bind the desired grammar to a C++ frontend via dynamic parsers like cpp-peglib is a real win.

My main project page is here, and there are tons of other examples. https://www.circle-lang.org/

I think Circle could also simplify the implementation of cpp-peglib. Since the grammar is almost always known at compile time, you could move parsing of that to compile time and benefit from the type system and error handling already built into the compiler. It would allow you to achieve the performance of a statically scheduled compiler (like a hand-written RD parser) while having the expressiveness of the dynamic system you built.

Thanks, sean

yhirose commented 5 years ago

@seanbaxter, it looks very interesting project, and I am surprised to see that cpp-peglib can be empowered greatly by espicially @expressions. I'll take a look at it more when I have time. Thanks a lot for letting me know the wonderful project!