introduction to parsing time to strip whitespace since whitespace (apart from newlinesis allowed as part of nameyet we don' want any leading or trailing whitespace for the color parser element we have specified that the first character must be followed by exactly six hexadecimal digits (seven characters in all)or sequence of alphanumeric characters with the first character alphabetic we have chosen to handle empty nodes specially we define an empty node as left bracket followed by right bracketand replace the brackets with the value emptyblock which earlier in the file is defined as emptyblock this means that in the parser' results list we represent empty blocks with and as noted earlierwe represent new rows by an integer row count (which will always be nodes forward(node_data optional(color suppress(":")optional(namenode_data setparseaction(add_blocknode left_bracket node_data nodes right_bracket nodes <group(zeroormore(optional(new_rowsoneormore(node empty_node))we define nodes to be forward(parser elementsince we need to use it before we specify what it matches we have also introduced new parser element that isn' in the bnfnode_datawhich matches the optional color and optional name we give this parser element parse action that will create new blockso each time node_data is encountered block will be added to the parser' results list the node parser element is defined very naturally as direct translation of the bnf notice that both the node_data and nodes parser elements are optional (the former consisting of two optional elementsthe latter quantified by zero or more)so empty nodes are correctly allowed finallywe can define the nodes parser element since it was originally created as forward(we must append parser elements to it using <here we have set nodes to be zero or more of an optional new row and one or more nodes notice that we put node before empty_node--since pyparsing matches left to right we normally order parser elements that have common prefixes from longest to shortest matching we have also grouped the nodes parser element' results using group()--this ensures that each nodes is created as list in its own right this means that node that contains nodes will be represented by block for the nodeand by list for the contained nodes--and which in turn may contain blocksor integers for empty nodes or new rowsand so on it is because of this recursive structure that we had to create nodes as forward()and also why we must use the <operator (which in pyparsing is used to append)to add the group(parser element and the elements it contains to the nodes element