formula ::('forall'exists'symbol ':formula formula '->formula right associative formula '|formula left associative formula '&formula left associative '~formula '(formula ')term '=term 'true'falseterm ::symbol symbol '(term_list ')term_list ::term term ',term_list symbol ::[ -za- ]\wfigure bnf for first-order logic binary operators as for precedencethe order is from lowest to highest in the order shown in the bnf for the first few alternativesthat isforall and exists have the lowest precedencethen ->then |then and the remaining alternatives all have higher precedence than those mentioned here before looking at the parser itselfwe will look at the import and the line that follows it since they are different than before from pyparsing_py import (alphanumsalphasdelimitedlistforwardgroupkeywordliteralopassocoperatorprecedenceparserelementparseexceptionparsesyntaxexceptionsuppresswordparserelement enablepackrat(memoizing the import brings in some things we haven' seen before and that we will cover when we encounter them in the parser the enablepackrat(call is used to switch on an optimization (based on memoizingthat can produce considerable speedup when parsing deep operator hierarchies if we do this at all it is best to do it immediately after importing the pyparsing_py module--and before creating any parser elements although the parser is shortwe will review it in three parts for ease of explanationand then we will see how it is called we don' have any parser actions since all we want to do is to get an ast (abstract syntax tree)-- list representing what we have parsed--that we can post-process later on if we wish left_parenthesisright_parenthesiscolon map(suppress"():"forall keyword("forall"for more on packrat parsingsee bryan ford' master' thesis at pdos csail mit edu/~bafordpackrat