yacc [Johnson, 1978] and bison [Corbett and Stallman], both, accept a table of grammar rules in BNF and actions written in C or a dialect such as Objective C or C++ and construct a C function to recognize a sentence.
If some input is acceptable to the right hand side of a rule the corresponding action is executed. One can think of the action as an observer for the rule.
A rule acts as a pattern to select part of the input and carry out the action on it; however, because the right hand side can contain nonterminals, the rules can call each other.
yacc and bison are grammar checkers because they test if a grammar is suitable for the parsing technique (LaLonde LR(1), not quite LR(1)). If it is, the grammar is not ambiguous.
Even if the table contains no actions, yacc and bison will produce a function that together with a scanner can check if an input sequence is a sentence for the grammar.