The following program simulates a parser/acceptor for an arbitrary deterministic finite automaton (DFA). When this and a state table program are loaded into Prolog, the parser/acceptor may be used to check inputs to the DFA to see whether or not they are acceptable. The program traces its action using write statements; these have been indented in order to better display the logical structure of the clauses.
parse(L) :- start(S),
trans(S,L).
trans(X,[A|B]) :-
delta(X,A,Y), /* X ---A---> Y */
write(X),
write(' '),
write([A|B]),
nl,
trans(Y,B).
trans(X,[]) :-
final(X),
write(X),
write(' '),
write([]), nl.
As an example, the following Prolog code specifies a state table for a DFA that accepts the language (a,b)*ab(a,b)* .
delta(0,a,1). delta(0,b,0). delta(1,a,1). delta(1,b,2). delta(2,a,2). delta(2,b,2). start(0). final(2).
A state diagram for this machine is as follows:
Suppose that both the driver program and the state table program are loaded ...
?- parse([b,b,a,a,b,a,b]). 0 [b,b,a,a,b,a,b] 0 [b,a,a,b,a,b] 0 [a,a,b,a,b] 1 [a,b,a,b] 1 [b,a,b] 2 [a,b] 2 [b] 2 [] yes ?- parse([b,b,a]). 0 [b,b,a] 0 [b,a] 0 [a] no
Exercise 2.14 Modify dfadrivr.pro so that it becomes a parser for NFAs, nondeterministic finite automata. Why is this extension such a natural one for Prolog?
Exercise 2.15 Using the DFA simulator presented here as motivation, design a Prolog simulator for Turing machines.