4 ms·
I may just be sleep-deprived, but I got Token tok; while ((tok = gettoken()) != END) while (!shift(tok)) if (!reduce(tok)) return ERROR;
by abecedarius 17y ago
I may just be sleep-deprived, but I got
Token tok;
while ((tok = gettoken()) != END)
while (!shift(tok))
if (!reduce(tok))
return ERROR;
return ACCEPT;
- nkurz 17y agoLooks right to me. But does this strike you as clearer than the original? I like that the original makes it very clear that we only return ACCEPT if we reach END; that after a successful shift we continue reading; that after a successful reduce we shift again; and that we only return ERROR if a reduce fails. I think yours works the same, but for me at least it takes longer to parse. If I were actually debugging yours, I might even resort to looking at the compiled code with objdump and writing the labels in by hand. Presuming it's correct, I bet this would result in something that looked a lot like the original!
- abecedarius 17y agoClarity's in the eye of the beholder, yes. I had to scratch my head over the original to deduce that, ah, for each token before END, there are 0 or more attempts to reduce, until we can shift (exactly once). To me, that's a clearer description of what we're trying to do: more declarative. It directly reflects a grammar: (!END reduce* shift)* END. If we can "parse" that grammar, we get ACCEPT, else ERROR. But it's true that different expressions make different things clear. Structured programming helps most when it gets you to mirror the data's structure in the code.