3 ms·
Yes. The second version is difficult to understand when there's a need to add new states or modify the states. The first version has a straightforward structu
by ww520 3y ago
Yes. The second version is difficult to understand when there's a need to add new states or modify the states. The first version has a straightforward structure and shape, making it easier to understand and update the state machine.
- barrkel 3y agoI don't agree. The second version is the typical way hand-written compiler lexers are written, and they're straightforward to add new "states" to, or to modify the states. The program counter is where you're "at", and the state space is normally straightforward. In fact it only gets complicated when additional non-control-flow state has been added. A typical hand-written lexer looks a bit like this (EOF testing omitted for clarity): // skip whitespace while isWhiteSpace(peekChar()) nextChar() // determine token type switch (peekChar()) case isAlpha start := currentPosition() nextChar() while isAlphaNumeric(peekChar()) nextChar() tokenType = IDENT tokenValue = substring(start, currentPosition()) case isNumeric start := currentPosition() nextChar() while isNumeric(peekChar()) nextChar() tokenType = INT tokenValue = substring(start, currentPosition()) tokenAsInt = int(tokenValue) case '+' nextChar() tokenType = PLUS // and so on Adding new cases to this is trivial. Nested context-specific lexical details (like escape codes in strings) aren't merged with a global state machine, and can be handed off to subroutines, enabling a modularity which is less confusing than having multiple state machines.
- ww520 3y agoIsn’t what you wrote the first version?