I have worked with a few parsers (Yacc, Bison and Menhir). If I remember correctly, all of them allow for a rule to be empty. Here is an example of what I mean using Menhir, it is the one I have used the most.
some_list:
| {[]}
| some_non_empty_list { $1 }
some_non_empty_list:
| SEMICOLON some_list { $2 }
| element { [$1] }
| element some_non_empty_list { $1 :: $2 }
The important part is that some_list that can reduce on nothingness.
My current understanding of the algorithm to build a parsing table (build NFA, build DFA from the NFA, minimize) leads me to think that this would lead to shift/reduce conflicts all over the place. But it clearly doesn't, because my code worked back then.
So how to build a parsing table that can accept those empty rules?