block has no name and the color white the children list contains blocks and nones--the latter representing new row markers rather than rely on users of the block class remembering all of these conventionswe have provided some module methods to abstract them away class blockdef __init__(selfnamecolor="white")self name name self color color self children [def has_children(self)return bool(self childrenthe block class is very simple the has_children(method is provided as convenience for the blockoutput py module we haven' provided any explicit api for adding childrensince clients are expected to work directly with the children list attribute get_root_block lambdablock(nonenoneget_empty_block lambdablock(""get_new_row lambdanone is_new_row lambda xx is none lambda functions these four tiny helper functions provide abstractions for the block class' conventions they mean that programmers using the block module don' have to remember the conventionsjust the functionsand also give us little bit of wiggle room should we decide to change the conventions later on now that we have the block class and supporting functions (all defined in the block py module file imported by the blocks py program that contains the parser)we are ready to write blk parser the parser will create root block and populate it with children (and children' childrenetc )to represent the parsed blk fileand which can then be passed to the blockoutput save_blocks_as_svg(function the parser is recursive descent parser--this is necessary because the blocks format can contain nested blocks the parser consists of data class that is initialized with the text of the file to be parsed and that keeps track of the current parse position and provides methods for advancing through the text in additionthe parser has group of parse functions that operate on an instance of the data classadvancing through the data and populating stack of blocks some of these functions call each other recursivelyreflecting the recursive nature of the data which is also reflected in the bnf