[0] https://github.com/lourencovales/codecrafters/blob/master/sh...
I have seen this misconception many times
In Oils, we have some pretty minor elaborations of the standard model, and it makes things a lot easier
How to Parse Shell Like a Programming Language - https://www.oilshell.org/blog/2019/02/07.html
Everything I wrote there still holds, although that post could use some minor updates (and OSH is the most bash-compatible shell, and more POSIX-compatible than /bin/sh on Debian - e.g. https://pages.oils.pub/spec-compat/2025-11-02/renamed-tmp/sp... )
---
To summarize that, I'd say that doing as much work as possible in the lexer, with regular languages and "lexer modes", drastically reduces the complexity of writing a shell parser
And it's not just one parser -- shell actually has 5 to 15 different parsers, depending on how you count
I often show this file to make that point: https://oils.pub/release/0.37.0/pub/src-tree.wwz/_gen/_tmp/m...
(linked from https://oils.pub/release/0.37.0/quality.html)
Fine-grained heterogenous algebraic data types also help. Shells in C tend to use a homogeneous command* and word* kind of representation
https://oils.pub/release/0.37.0/pub/src-tree.wwz/frontend/sy... (~700 lines of type definitions)
For side-projects, I have to ask myself if I'm writing a parser, or if I'm building something else; e.g. for a toy programming language, it's way more fun to start with an AST and play around, and come back to the parser if you really fall in love with it.
[0] https://gist.github.com/rrampage/5046b60ca2d040bcffb49ee38e8...
controlling terminal
session leader
job control
The parser was easy in comparison.The first line was always to turn off echo, and I've always wondered why that was a decision for batch script. Or I'm misremembering. 30 years of separation makes it hard to remember the details.
I always include $? in the prompt, so I guess I can say it does print the result of the evaluation.
It's what they use for /bin/sh, it has everything that a complete shell needs (including a mechanism for providing command completions) and has code that is much easier to read than bash or zsh.
Something that I also would recommend is the design document for the plan9 rc shell; it is a worthwhile read for anybody interested in shells: https://doc.cat-v.org/plan_9/4th_edition/papers/rc
An implementation is also available if one wants to look at how it could be done: https://github.com/rakitzis/rc
https://www.destroyallsoftware.com/screencasts/catalog/shell...
Marc Rochkind's book Avanced UNIX Programming implemented a basic shell, through iterations. You can see the first at e.g. here https://github.com/gmarler/AUPv2/blob/master/c5/sh0.c
It might be a bit old too. The book is very good but again, quite old. There seem to be free copies of it on the net.
BTW, does anyone know if Marc Rochkind is alive? His site basepath.com seems to be for sale :-(
Also helpful may be running strace on your shell, then reviewing the output line by line to make sure you understand each. This is a VERY instructive exercise to do in general.
IIRC readline uses a `char *` internally since the length of a user-edited line is fairly bounded.