State Machines (was Re: gotos)
Peter da Silva
peter at sugar.UUCP
Sat May 7 23:50:09 AEST 1988
I submit that there is one case where gotos are no worse and possibly better
than the alternative. And that is state machine type code, as is found in
lexers. It's rather a narrow category, but I feel it's a valid one. I don't
know if you're arguing against having a goto in a language at all, but here's
one reason to leave it in...
Objection #1 I'll cover immediately: "Use Lex".
You can't always get lex.
In fact, for most machines and languages there is no lex or anything
like it. Say, Fortran on a Unisys 1100. Most machines *aren't* UNIX.
Even using Lex on a UNIX box and massaging the tables doesn't help
when the program has to be maintained in the non-UNIX environment. Even when
you have all the UNIX tools, it's not always cool. I once wrote a recursive-
descent parser in Forth for a real-time applications language in something like
two months, including a line-oriented language-oriented editor. The guy in
charge of the job didn't like this, and went away for 6 months playing with
doing it with Yacc and massaging the tables. Eventually he and the project were
canned.
Objection #2 is something like: "Write a table-driven scanner". It's also
expressed in terms of using a big while loop and a case statement to do the
state machine.
You still have to maintain the state machine. The table-driven one
has to be generated somehow, and unless you have Lex or its equivalent it's
going to be expressed in terms of states and transitions... just like the
goto-based version. The same can be said of the case statement. All you're
doing here is hiding the gotos. They're still there:
ENDSTMT:
IF(TOKEN .EQ. NEWLINE) THEN
CALL OUTPUT(SCANNEDLINE)
GOTO NEWSTMT
ELSE IF(TOKEN .EQ. COMMENT) THEN
GOTO ENDSTMT
ELSE
GOTO SYNERR
ENDIF
Is no worse than (and is in fact equivalent to):
ELSE IF(STATE .EQ. ENDSTMT) THEN
IF(TOKEN .EQ. NEWLINE) THEN
CALL OUTPUT(SCANNEDLINE)
STATE = NEWSTMT
ELSE IF(TOKEN .EQ. COMMENT) THEN
STATE = ENDSTMT
ELSE
STATE = SYNERR
ENDIF
And is much better than:
DATA STATABL(1,ENDSTMT) /NEWLINE, ACTIONOUT, NEWSTMT/
DATA STATABL(2,ENDSTMT) /COMMENT, 0, ENDSTMT/
DATA STATABL(3,ENDSTMT) /0, 0, SYNERR/
with some special code to decode the actions.
--
-- Peter da Silva `-_-' ...!hoptoad!academ!uhnix1!sugar!peter
-- "Have you hugged your U wolf today?" ...!bellcore!tness1!sugar!peter
-- Disclaimer: These aren't mere opinions, these are *values*.
More information about the Comp.lang.c
mailing list