We've now seen the LL(1) parsing algorithm - in particular, the use of an LL(1) parse table in recognizing a string as part of a context-free language. In order to explore the process of construction these tables, we must first cover the underlying concept of first sets.
Observe the following CFG and corresponding LL(1) parse table:
Example
S → AD
A → ac
A → bc
D → d
Our parse table is:
a | b | c | d | |
S | 1 | 1 | ||
A | 2 | 3 | ||
D | 4 |
A few observations from the table above:
Takeaways:
Definition
We will define FIRST(n) as a function that maps a nonterminal symbol to a set of terminal symbols in relation to a context-free grammar G.
We can build up our definition of FIRST(n) as follows:
Example
S → a B
B → b C
C → c
Here:
In this example, all productions start with a nonterminal, so we are only concerned with looking at the direct productions for each nonterminal symbol.
Example
S → A
A → a B
A → B
B → b C
B → C
C → c
Here:
Here, we have illustrated how we can derive first sets indirectly through productions whose right-hand side starts with a nonterminal.
Note
c ∈ FIRST(S) because S →* c. This simplified notation for a string derivation can be used to further understand and express first sets in this context.
Example
S → A
A → S
Here, FIRST(S) = FIRST(A) = {}.
Because we don't have any productions starting with a terminal on the right-hand side, we have no first sets to extend through our productions starting with a nonterminal.
In this example, it's also worth noting that a production cycle does not break our calculation - it simply adds no further information once it has been fully explored.
Example
S → aB
B → bD
B → CD
B → D
C → c
D → d
D → S
We can start building up our first sets directly via produced terminals as follows:
Then, we can extend our first sets via nonterminals:
Combining these results, we have:
Notice how we followed all branches and nonterminal chains to reach our final result.
In this section, we illustrated how to calculate the first sets for nonterminals in a context-free grammar. In the next section, we will show how to convert this information into an LL(1) parse table.
GitHub Repository: https://github.com/bprollinson/ripal
Copyright © 2017 Brendan Rollinson-Lorimer