Pushdown Automata
(Content adapted from Critchlow & Eck)
In the previous chapter, we saw that there is a neat correspondence between regular expressions and finite automata. That is, a language is generated by a regular expression if and only if that language is accepted by a finite automaton. Finite automata come in two types, deterministic and nondeterministic, but the two types of finite automata are equivalent in terms of their ability to recognize languages. So, the class of regular languages can be defined in two ways: either as the set of languages that can be generated by regular expressions or as the set of languages that can be recognized by finite automata (either deterministic or nondeterministic).
In this chapter, we have introduced the class of context-free languages, and we have considered how context-free grammars can be used to generate context-free languages. You might wonder whether there is any type of automaton that can be used to recognize context-free languages. In fact, there is: The abstract machines known as pushdown automata can be used to define context-free languages. That is, a language is context-free if and only if there is a pushdown automaton that accepts that language.
A pushdown automaton is essentially a finite automaton with an auxiliary data structure known as a stack. A stack consists of a finite list of symbols. Symbols can be added to and removed from the list, but only at one end of the list. The end of the list where items can be added and removed is called the top of the stack. The list is usually visualized as a vertical "stack" of symbols, with items being added and removed at the top. Adding a symbol at the top of the stack is referred to as pushing a symbol onto the stack, and removing a symbol is referred to as popping an item from the stack. During each step of its computation, a pushdown automaton is capable of doing several push and pop operations on its stack (this in addition to possibly reading a symbol from the input string that is being processed by the automaton).
Before giving a formal definition of pushdown automata, we will look at how they can be represented by transition diagrams. A diagram of a pushdown automaton is similar to a diagram for an NFA, except that each transition in the diagram can involve stack operations. We will use a label of the form / on a transition to mean that the automaton consumes from its input string, pops from the stack, and pushes onto the stack. can be either or a single symbol. and are strings, possibly empty. (When a string is popped from the stack, must be the top symbol on the stack, followed by , etc.; for to be pushed onto a stack, the symbols are pushed in the order , so that ends up on the top of the stack.) For example, consider the following transition diagram for a pushdown automaton:

This pushdown automaton has start state and one accepting state, . It can read strings over the alphabet . The transition from to , labeled with /1, means that if the machine is in state , then it can read an from its input string, pop nothing from the stack, push 1 onto the stack, and remain in state . Similarly, the transition from to means that if the machine is in state , it can read a from its input string, pop a 1 from the stack, and push nothing onto the stack. Finally, the transition from state to , labeled with /, means that the machine can transition from state to state without reading, pushing, or popping anything.
Note that the automation can follow transition / only if the next symbol in the input string is and if is on the top of the stack. When it makes the transition, it consumes the from input and pops the from the stack. Since in this case, the automaton pushes (that is, no symbols at all) onto the stack, the net change in the stack is simply to pop the 1.
We have to say what it means for this pushdown automaton to accept a string. For , we say that the pushdown automaton accepts if and only if it is possible for the machine to start in its start state, , read all of , and finish in the accepting state, , with an empty stack. Note in particular that it is not enough for the machine to finish in an accepting state—it must also empty the stack.1
It's not difficult to see that with this definition, the language accepted by our pushdown automaton is . In fact, given the string , the machine can process this string by following the transition from to times. This will consume all the 's and will push 1's onto the stack. The machine can then jump to state and follow the transition from to times. Each time it does so, it consumes one from the input and pops one 1 from the stack. At the end, the input has been completely consumed and the stack is empty. So, the string is accepted by the automaton. Conversely, this pushdown automaton only accepts strings of the form , since the only way that the automaton can finish in the accepting state, , is to follow the transition from to some number of times, reading 's as it does so, then jump at some point to , and then follow the transition from to some number of times, reading 's as it does so. This means that an accepted string must be of the form for some . However, in reading this string, the automaton pushes 1's onto the stack and pops 1's from the stack. For the stack to end up empty, must equal , which means that in fact the string is of the form , as claimed.
Here are two more examples. These pushdown automata use the capability to push or pop more than one symbol at a time:

The automaton on the left accepts the language . Each time it reads an , it pushes either one or two 1's onto the stack, so that after reading 's, the number of 1's on the stack is between and . If the machine then jumps to state , it must be able to read exactly enough 's to empty the stack, so any string accepted by this machine must be of the form with . Conversely, any such string can be accepted by the machine. Similarly, the automaton on the right above accepts the language . To accept , it must push 1'a onto the stack and then pop one or two 1's for each b; this can succeed only if the number of 's is between and .
Note that an NFA can be considered to be a pushdown automaton that does not make any use of its stack. This means that any language that can be accepted by an NFA (that is, any regular language) can be accepted by a pushdown automaton. Since the language is context-free but not regular, and since it is accepted by the above pushdown automaton, we see that pushdown automata are capable of recognizing context-free languages that are not regular, therefore pushdown automata are strictly more powerful than finite automata.
Formal Definition
Although it is not particularly illuminating, we can give a formal definition of pushdown automaton. The definition does at least make it clear that the set of symbols that can be used on the stack is not necessarily the same as the set of symbols that can be used as input.
A pushdown automaton is specified by six components where
- is a finite set of states.
- is an alphabet. is the input alphabet for .
- is an alphabet. is the stack alphabet for .
- is the start state of .
- is the set of final or accepting states in .
- is the set of transitions in . can be taken to be a finite subset of the set . An element of represents a transition from state to state in which reads from its input string, pops from the stack, and pushes onto the stack.
We can then define the language accepted by a pushdown automaton to be the set .
With this definition, the class of languages accepted by pushdown automata is the same as the class of languages generated by context-free grammars.
Theorem: Let be an alphabet, and let be a language over . Then is context-free if and only if there is a pushdown automaton whose input alphabet is such that .
We will not prove this theorem, but we do discuss how one direction can be proved. Suppose that is a context-free language over an alphabet . Let be a context-free grammar for . Then we can construct a pushdown automaton that accepts . In fact, we can take where , , , and contains transitions of the forms
- ;
- , for ; and
- , for each production in .
The transition lets move from the start state to the accepting state while reading no input and pushing onto the stack. This is the only possible first move by .
A transition of the form , for , allows to read