introduction to parsing tokens ("node_start""node_end""color""name""new_rows""empty_node"pyparsing blocks parser blk bnf t_node_start "\[t_node_end "\]t_color "(?:\#[\da-fa- ]{ }|[ -za- ]\ *):t_name "[^][/\ ]+t_new_rows "/+t_empty_node "\[\]the regexes are taken directly from the bnfexcept that we have chosen to disallow newlines in names in additionwe have defined t_ignore regex to skip spaces and tabsand t_newline(and t_error(functions that are the same as before except that t_error(raises custom lexerror with its error message rather than printing the error message with the tokens set upwe are ready to prepare for lexing and then to do the lexing stack [block get_root_block()block none brackets lexer ply lex lex(trylexer input(textfor token in lexeras with the previous blocks parsers we begin by creating stack ( listwith an empty root block this will be populated with child blocks (and the child blocks with child blocksetc to reflect the blocks that are parsedat the end we will return the root block with all its children the block variable is used to hold reference to the block that is currently being parsed so that it can be updated as we go we also keep count of the brackets purely to improve the error reporting one difference from before is that we do the lexing and the parsing of the tokens inside try except suite--this is so that we can catch any lexerror exceptions and convert them to valueerrors if token type ="node_start"brackets + block block get_empty_block(stack[- children append(blockstack append(blockelif token type ="node_end"brackets - if brackets raise lexerror("too many ']' "