I hear you that it is technically possible to make . behave the same way as -> for raw pointers - but perhaps you should ask yourself why Ritchie and Kernighan didn't do it. I am quite sure they saw the opportunity. Perhaps they thought it was a dangerous idea?
I couldn't really speak to K&R or BS... but I can actually, I'm not sure they could have, because they were code->assembly, and the two are quite different on how you have to get that address... but now there's code->meta->optimizing pipeline->assembly. There's something like it didn't really occur to me, I used K&R pamphlet-book, and I actually caught that '->' reads the memory location and . uses the base of a more statically allocated thing... but then that's from stepping through code with turbo C's debugger maybe.
A tail call between two fucntions in an error state looks like infinite recursion? Except the call to the other would guarantee to not trigger the other error path again?
isStruct() { if( is !pointer && object ) { look up name toekn } else { call isPointer }
isPointer { if( -> ) { if is pointer ) { look up next name token}} else { call is Struct }
something like that? so probably better to just gernerate an exception there?