In my day there was a unit on compiler optimization, with a code size contest. Constant propagation, register allocation, dead code elimination. Now it seems they replaced that with a section involving writing a loader for a ELF-like file format in assembly language
Frankly, I'd expect someone who's never implemented a compiler before make the mistake of not using a parser generator because they are daunted by yacc and think their language is not going to need the complexity of an extra compile step.
By the way if you don't need very fancy features, writing parsers with parser combinators is very easy and fun and doesn't require any metaprogramming tools. You can even write your own little parser combinator library because the concept is so simple.
Hand-written recursive descent parsers are quite commonly used in production compilers (e.g. GCC, Rust). See e.g. here: https://softwareengineering.stackexchange.com/questions/2546... They don’t seem to be particularly difficult to maintain.
And just absolutely talking, 10-20k lines of code is never nothing. That's months if not years of coding, that has to maintained and expanded upon as your project grows.
Once you get used to writing recursive descent parsers you can bash them out quite quickly. You can write a mostly-working parser for a programming language in a few days. 10-20k lines of code might sound like quite a lot, but it's mostly repetitive code that's easy to get right and easy to write tests for.
Recursive descent parsers can often be easier to maintain than parser generator based parsers because you don't have to keep hacking around the limitations of the generator. For example, C and C++ don't permit any kind of clean separation between lexing, parsing and symbol resolution.
Even gcc's C parser and lexer combined are only about 30,000 LOC, depending on which files you count besides the main parser module: https://github.com/gcc-mirror/gcc/blob/master/gcc/c/c-parser... And this is code written in Cish C++. In a higher-level language it could be significantly more concise.
Is this what you had in mind? Which language is best in your opinion for a parser?
If you want to use parser combinators, then something with basic support for functional programming (particularly closures and and a lightweight lambda syntax).
No deepness needed, the only thing you need to know is recursion.
Also SQL is even better than that because every query is it's own statement, so the parsing is dead simple. I totally get why he did it this way.
I’ve not spotted that - and I have a thing for bespoke editors! Could somebody link me up to the editor? A few cursory searches didn’t prove fruitful.
Obviously, now I’m curiouser about the secret editor :)
> And the text editor that I used to write SQLite is one that I wrote myself. [10]
But with no more details.
What the above comments showed in terms of what is taught at unis seem to be great starting points. Since he already knew classical stack-based VMs from the start, this maybe shows he learnt it at uni. Would love to ask him about it!
I think DRH picked a self-imposed constraint that sqlite would not have any external dependencies. A lot of his decisions are due to this constraint.
Yup. Also, having deep knowledge of the language is required.
SQLite's grammar is neat. Creating a compatible parser would make a fun project. Here's a pretty good example: https://github.com/bkiers/sqlite-parser (Actual ANTLR 4 grammar: https://github.com/bkiers/sqlite-parser/blob/master/src/main... )
Postgres, which tries to be compliant with the latest standards, however...
SQL-2016 is a beast. Not to mention all the dialects.
I'm updating my personal (soon to be FOSS) grammar from ANTLR 3 LL(k) to ANTLR 4 ALL(Star).
I've long had a working knowledge of SQL-92, with some SQL-1999 (eg common table expressions).
But the new structures and extensions are a bit overwhelming.
Fortunately, ANTLR project has ~dozen FOSS grammars to learn from. https://github.com/antlr/grammars-v4/tree/master/sql
They mostly mechanically translate BNFs to LL(k) with some ALL(Star). Meaning few take advantage of left-recursion. https://github.com/antlr/antlr4/blob/master/doc/left-recursi...
Honestly, I struggled to understand these grammars. Plus, not being conversant with the SQL-2016 was a huge impediment. Just finding a succinct corbis of test cases was a huge hurdle for me.
Fortunately, the H2 Database project is a great resource. https://github.com/h2database/h2database/tree/master/h2/src/...
Now for the exciting conclusion...
My ANTLR grammar which passes all of H2's tests diverges significantly any of the official or product specific BNFs.
Further, I found discrepancy between product specific BNFs and their implementations.
So a lot of trial & error is required for a "real world" parser. Which would explain why the professional SQL parsing tools ask for money.
I still think creating a parser for SQLite is a great project.
In about 99% of cases, for 99% of people, this is the wrong thing to do - but DRH pulled it off.
On the "why use flex/yacc ... when you can roll your own", I think the tradeoff is: if you have a deep understanding of theory of parsing and parser generators, then it's actually less mental effort for you to write your own from scratch, than it would be to learn the exact syntax and quirks and possibly bugs of someone else's implementation. Or to find out that some feature that's easy to implement from scratch, doesn't exist in the library.
I wonder, do we teach "classical" parsing that well anymore, in a way that could create the next generation's DRH?