introduction to parsing once lexing has finished we check that the brackets have balancedand if not we raise lexerror if lexerror occurred during lexingparsingor when we checked the bracketswe raise valueerror that contains an escaped str format(field name--the caller is expected to use this to insert the filenamesomething we cannot do here because we are given only the file' textnot the filename or file object at the end (not shown)we return stack[ ]this is the root block that should now have children (and which in turn might have children)representing the blk file we have parsed this block is suitable for passing to the blockoutput save_blocks_as_svg(functionjust as we did with the recursive descent and pyparsing blocks parsers parsing first-order logic pyparsing firstorder logic parser first-order logic bnf |in the last pyparsing subsection we created parser for first-order logic in this subsection we will create ply version that is designed to produce identical output to the pyparsing version setting up the lexer is very similar to what we did earlier the only novel aspect is that we keep dictionary of "keywordswhich we check whenever we have matched symbol (the equivalent to an identifier in programming languagehere is the lexer codecomplete except for the t_ignore regex and the t_newline(and t_error(functions which are not shown because they are the same as ones we have seen before keywords {"exists""exists""forall""forall""true""true""false""false"tokens (["symbol""colon""comma""lparen""rparen""equals""not""and""or""implies"list(keywords values())def t_symbol( ) "[ -za- ]\ * type keywords get( value"symbol"return t_equals "=t_not "~t_and "&t_or "\|t_implies "->t_colon ":t_comma ",t_lparen "\(t_rparen "\)