introduction to parsing is itself formula which may contain formulas and so on we don' have to concern ourselves with whitespace between tokens since we created t_ignore regex which told the lexer to ignore ( skipwhitespace in this examplewe could just as easily have created two separate functionssayp_formula_forall(and p_formula_exists()giving them one alternative of the bnf each and the same suite we chose to combine them--and some of the others--simply because they have the same suites formulas in the bnf have three binary operators involving formulas since these can be handled by the same suitewe have chosen to parse them using single function and bnf with alternatives def p_formula_binary( )"""formula formula implies formula formula or formula formula and formula"" [ [ [ ] [ ] [ ]the resultthat isthe formula stored in [ ]is simply list containing the left operandthe operatorand the right operand this code says nothing about precedence and associativity--and yet we know that implies is right-associative and that the other two are left-associativeand that implies has lower precedence than the others we will see how to handle these aspects once we have finished reviewing the parser' functions def p_formula_not( )"formula not formulap[ [ [ ] [ ]def p_formula_boolean( )"""formula false true"" [ [ def p_formula_group( )"formula lparen formula rparenp[ [ def p_formula_symbol( )"formula symbolp[ [ all these formula alternatives are unarybut even though the suites for p_formula_boolean(and p_formula_symbol(are the samewe have given each one its own function since they are all logically different from each other one slightly surprising aspect of the p_formula_group(function is that we set its value to be [ rather than [ [ ]this works because we already use lists to