kids these days, when I wrote my first compiler I had to write my own yacc equivalent, and parser
FYI: My generator allowed for dynamic resolution of shift/reduce conflicts which allows you to compile some languages yacc wont let you (languages that let you change the priority of operators for example)
Did something similar in 6800 assembly, left recursion of course limits you even more - but it helps fit that tiny tiny compiler into 2k.
I actually like yacc/bison - they're good for most purposes and deliberately designing a non-LALR (or more a non-LR) language on purpose (rather than because you don't know any better) is usually silly - you do need to 'get' the concept of building a parse tree from bottom up - assembling it from larger and larger snippets as you go
Oh and yacc/bison run about 10 times faster than equivalent I wrote 10 years before they existed so I'm not complaining
I tend to use the same bespoke lexical analyser I've used for years and hack it to suit - it includes support for symbol tables/etc and runs really fast, no need to reinvent the wheel
yacc and lex are handy to have around, but feel like Jurassic tools when compared to more modern parser generators tooling like ANTLR.